/*
(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;
}
|