Version 0.94.1 of the bladeenc mp3 encoder
[swftools.git] / lib / bladeenc / codec.c
diff --git a/lib/bladeenc/codec.c b/lib/bladeenc/codec.c
new file mode 100644 (file)
index 0000000..c6697ea
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+                       (c) Copyright 1998-2000 - Tord Jansson
+                       ======================================
+
+               This file is part of the BladeEnc MP3 Encoder, based on
+               ISO's reference code for MPEG Layer 3 compression, and might
+               contain smaller or larger sections that are directly taken
+               from ISO's reference code.
+
+               All changes to the ISO reference code herein are either
+               copyrighted by Tord Jansson (tord.jansson@swipnet.se)
+               or sublicensed to Tord Jansson by a third party.
+
+       BladeEnc is free software; you can redistribute this file
+       and/or modify it under the terms of the GNU Lesser General Public
+       License as published by the Free Software Foundation; either
+       version 2.1 of the License, or (at your option) any later version.
+
+
+
+       ------------    CHANGES    ------------
+
+       2000-11-22  Andre Piotrowski
+
+       -       big fix: module - original dist10 error - l3_sb_sample has to be of type 'L3SBS' not 'SBS'.
+       -       bug fix: codecInit() - don't reset fInit-huffman_read_flag - read_huffcodetab() is a memory eater!
+
+       2000-12-11  ap
+
+       -       reformatted
+       -       speed up: use single buffer
+*/
+
+#include       <stdlib.h>
+#include       <assert.h>
+
+#include       "common.h"
+#include       "l3psy.h"
+#include       "mdct.h"
+#include       "reservoir.h"
+#include       "formatbitstream2.h"
+#include       "l3bitstream.h"
+#include       "loop.h"
+#include       "encoder.h"
+#include       "codec.h"
+
+
+
+
+
+extern int                             fInit_fft;
+
+
+
+
+
+/************************************************************************/
+
+#define        SAMPLES_PER_FRAME               1152
+
+static L3SBS                                   l3_sb_sample;
+
+static layer                                   info;
+
+
+
+#if ORG_BUFFERS
+static short                                   buffer[2][1152];
+/*     static  float                                   snr32[32]; */
+static short                                   sam[2][2048];
+#else
+static FLOAT                                   buffer[2][2048];
+static int                                             buffer_idx;
+#endif
+
+
+
+static int                                             whole_SpF;
+
+static double                                  frac_SpF, slot_lag;
+
+static int                                             stereo, error_protection;
+
+static III_side_info_t                 l3_side;
+static CodecInitOut                    sOut;
+
+static frame_params                    fr_ps;
+
+
+
+char                                   *pEncodedOutput;
+int                                            outputBit;
+
+volatile double                        avg_slots_per_frame;
+
+
+
+
+
+/*____ codecInit() ____________________________________________________________*/
+
+CodecInitOut                   *codecInit (CodecInitIn *psIn)
+{
+       int                                             j;
+
+       /* Read psIn */
+
+       switch (psIn->frequency)
+       {
+               case 48000:  info.sampling_frequency = 1;  break;
+               case 44100:  info.sampling_frequency = 0;  break;
+               case 32000:  info.sampling_frequency = 2;  break;
+               default   :  return FALSE;
+       }
+
+       switch (psIn->mode)
+       {
+               case  0:  info.mode = MPG_MD_STEREO      ;  info.mode_ext = 0;  break;
+               case  2:  info.mode = MPG_MD_DUAL_CHANNEL;  info.mode_ext = 0;  break;
+               case  3:  info.mode = MPG_MD_MONO        ;  info.mode_ext = 0;  break;
+               default:  return FALSE;
+       }
+
+       j = 0;
+       while (j < 15  &&  bitratex[1][j] != psIn->bitrate)
+               j++;
+       info.bitrate_index    = j;
+
+       info.version          = 1;   /* Default: MPEG-1 */
+       info.emphasis         = psIn->emphasis;
+       info.extension        = psIn->fPrivate;
+       info.copyright        = psIn->fCopyright;
+       info.original         = psIn->fOriginal;
+       info.error_protection = psIn->fCRC;
+
+
+/*_______ Static-fix _______________*/
+
+
+       fInit_mdct_sub = 0;
+       fInit_mdct = 0;
+
+       fInit_fft = 0;
+
+       fInit_iteration_loop = 0;
+/*     DON'T DO THAT ALL THE TIME
+       fInit_huffman_read_flag = 0;
+*/
+
+       fixStatic_loop();
+
+       l3_side.main_data_begin = 0;
+       fixStatic_reservoir();
+
+
+/*___________________________________*/
+
+    psycho_anal_init (psIn->frequency);
+       initWindowFilterSubband ();
+       initFormatBitstream ();
+
+/*     clear buffers */
+       memset ((char *) l3_sb_sample, 0, sizeof(l3_sb_sample));
+    memset((char *) buffer, 0, sizeof(buffer));
+/*    memset((char *) snr32, 0, sizeof(snr32));*/
+#if ORG_BUFFERS
+    memset((char *) sam, 0, sizeof(sam));
+#endif
+
+
+
+    fr_ps.header         = &info;
+    fr_ps.tab_num        = -1;   /* no table loaded */
+    fr_ps.alloc          = NULL;
+    fr_ps.actual_mode = info.mode;
+    fr_ps.stereo         = (info.mode == MPG_MD_MONO) ? 1 : 2;
+       fr_ps.sblimit     = SBLIMIT;
+    fr_ps.jsbound        = SBLIMIT;
+
+    
+    stereo = fr_ps.stereo;
+    error_protection = info.error_protection;
+
+    avg_slots_per_frame =
+               ((double) SAMPLES_PER_FRAME / s_freq[1][info.sampling_frequency]) *
+               ((double) bitratex[1][info.bitrate_index] / 8.0);
+    whole_SpF = (int) avg_slots_per_frame;
+    frac_SpF  = avg_slots_per_frame - (double) whole_SpF;
+    slot_lag  = -frac_SpF;
+
+/*    if (frac_SpF == 0)
+       info.padding = 0;
+*/
+       genNoisePowTab();
+
+/*________________________*/
+
+
+       if( stereo != 2 )
+               sOut.nSamples = SAMPLES_PER_FRAME;
+       else
+               sOut.nSamples = SAMPLES_PER_FRAME*2;
+
+       sOut.bufferSize = 2048;
+
+       return  &sOut;                  /* How many samples we want in each chunk... */
+}
+
+
+
+
+
+/*____ codecEncodeChunk() _____________________________________________________*/
+
+unsigned int                   codecEncodeChunk
+(
+       int                                             nSamples,
+       short                                   *pSamples,
+       char                                    *pDest
+)
+{
+       static  double                          xr[2][2][576];
+       static  double                          xr_dec[2][2][576];
+       static  double                          pe[2][2];
+       static  int                                     l3_enc[2][2][576];
+       static  III_psy_ratio           ratio;
+       static  III_scalefac_t          scalefac;
+       int                                                     gr, ch;
+       int                                                     mean_bits, sideinfo_len;
+       int                                                     bitsPerFrame;
+       int                                                     j;
+
+/*
+       static  int                                     fFirst = TRUE;
+
+       if (fFirst)
+       {
+               memset ((char *) &xr      , 0, sizeof(xr));
+               memset ((char *) &xr_dec  , 0, sizeof(xr_dec));
+               memset ((char *) &pe      , 0, sizeof(pe));
+               memset ((char *) &l3_enc  , 0, sizeof(l3_enc));
+               memset ((char *) &ratio   , 0, sizeof(ratio));
+               memset ((char *) &l3_side , 0, sizeof(l3_side));
+               memset ((char *) &scalefac, 0, sizeof(scalefac));
+
+               fFirst = FALSE;
+       }
+*/
+
+
+/* rebuffer audio */
+
+#if ORG_BUFFERS
+       rebuffer_audio (buffer, pSamples, nSamples, stereo);
+#else
+       rebuffer_audio (pSamples, buffer, &buffer_idx, nSamples, stereo);
+#endif
+
+
+/* psychoacoustic model */
+
+       for (gr = 0;  gr < 2;  gr++)
+               for (ch = 0;  ch < stereo;  ch++)
+                       psycho_anal
+                       (
+#if ORG_BUFFERS
+                               &buffer[ch][gr*576],
+                               &sam[ch][0],
+#else
+                       buffer[ch],
+                       (buffer_idx+gr*576) & 2047,
+#endif
+                               ch,
+                               3,
+                               /*snr32,*/
+                               &ratio.l[gr][ch][0],
+                               &ratio.s[gr][ch][0],
+                               &pe[gr][ch],
+                               &l3_side.gr[gr].ch[ch].tt
+                       );
+
+
+/* polyphase filtering */
+
+       for (gr = 0;  gr < 2;  gr++)
+       {
+               int             gr_plus_1 = gr_idx[gr+1];
+
+               for (ch = 0;  ch < stereo;  ch++)
+               {
+                       for (j = 0;  j < 18;  j++)
+                       {
+                               windowFilterSubband
+                               (
+#if ORG_BUFFERS
+                                       &buffer[ch][gr*18*32+32*j],
+                                       ch,
+#else
+                                       buffer[ch],
+                                       (buffer_idx+768-480+gr*18*32+32*j) & 2047,
+#endif
+                                       l3_sb_sample[ch][gr_plus_1][j]
+                               );
+                       }
+               }
+       }
+
+
+/* apply mdct to the polyphase outputs */
+
+       mdct_sub (&l3_sb_sample, xr, stereo, &l3_side, 2);
+
+
+       pEncodedOutput = pDest;
+       outputBit = 8;
+       pEncodedOutput[0] = 0;
+
+
+       if (frac_SpF != 0)
+       {
+               if (slot_lag > (frac_SpF-1.0))
+               {
+                       slot_lag -= frac_SpF;
+                       info.padding = 0;
+               }
+               else
+               {
+                       info.padding = 1;
+                       slot_lag += (1-frac_SpF);
+               }
+       }
+
+       bitsPerFrame = 8 * whole_SpF + (info.padding * 8);
+
+
+/* determine the mean bitrate for main data */
+
+       sideinfo_len = 32;
+
+       if (stereo == 1)
+               sideinfo_len += 136;
+       else
+               sideinfo_len += 256;
+
+       if (info.error_protection)
+               sideinfo_len += 16;
+
+       mean_bits = (bitsPerFrame - sideinfo_len) / 2;
+
+
+/* bit and noise allocation */
+
+       iteration_loop
+       (
+               pe,
+               xr,
+               &ratio,
+               &l3_side,
+               l3_enc,
+               mean_bits,
+               stereo,
+               xr_dec,
+               &scalefac,
+               &fr_ps,
+               0,
+               bitsPerFrame
+       );
+
+
+/* write the frame to the bitstream */
+
+       III_format_bitstream
+       (
+               bitsPerFrame,
+               &fr_ps,
+               l3_enc,
+               &l3_side,
+               &scalefac,
+               xr,
+               NULL,
+               0
+       );
+
+
+       return  pEncodedOutput - pDest;
+}
+
+
+
+
+
+/*____ codecExit() ____________________________________________________________*/
+
+unsigned int                   codecExit (char *pDest)
+{
+       pEncodedOutput = pDest;
+       outputBit = 8;
+       pEncodedOutput[0] = 0;
+
+       psycho_anal_exit ();
+       exitFormatBitstream ();
+       III_FlushBitstream ();
+
+       return pEncodedOutput - pDest;
+}
+
+
+
+
+
+/*____ codecFlush() _________________________________________________________*/
+
+unsigned int                   codecFlush (char *pDest)
+{
+       pEncodedOutput = pDest;
+       outputBit = 8;
+       pEncodedOutput[0] = 0;
+
+       flushFrame ();
+
+       whole_SpF = (int) avg_slots_per_frame;
+       frac_SpF  = avg_slots_per_frame - (double) whole_SpF;
+       slot_lag  = -frac_SpF;
+
+       l3_side.main_data_begin = 0;
+       fixStatic_reservoir ();
+
+       return pEncodedOutput - pDest;
+}
+
+
+