diff options
Diffstat (limited to 'lib/liblame/libmp3lame/encoder.c')
-rw-r--r-- | lib/liblame/libmp3lame/encoder.c | 565 |
1 files changed, 565 insertions, 0 deletions
diff --git a/lib/liblame/libmp3lame/encoder.c b/lib/liblame/libmp3lame/encoder.c new file mode 100644 index 0000000000..d0549ca3c3 --- /dev/null +++ b/lib/liblame/libmp3lame/encoder.c @@ -0,0 +1,565 @@ +/* + * LAME MP3 encoding engine + * + * Copyright (c) 1999 Mark Taylor + * Copyright (c) 2000-2002 Takehiro Tominaga + * Copyright (c) 2000-2005 Robert Hegemann + * Copyright (c) 2001 Gabriel Bouvigne + * Copyright (c) 2001 John Dahlstrom + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* $Id: encoder.c,v 1.103.2.1 2008/08/05 14:16:06 robert Exp $ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + + +#include "lame.h" +#include "machine.h" +#include "encoder.h" +#include "util.h" +#include "lame_global_flags.h" +#include "newmdct.h" +#include "psymodel.h" +#include "lame-analysis.h" +#include "bitstream.h" +#include "VbrTag.h" +#include "quantize_pvt.h" + + + +/* + * auto-adjust of ATH, useful for low volume + * Gabriel Bouvigne 3 feb 2001 + * + * modifies some values in + * gfp->internal_flags->ATH + * (gfc->ATH) + */ +static void +adjust_ATH(lame_internal_flags const *const gfc) +{ + FLOAT gr2_max, max_pow; + + if (gfc->ATH->use_adjust == 0) { + gfc->ATH->adjust = 1.0; /* no adjustment */ + return; + } + + /* jd - 2001 mar 12, 27, jun 30 */ + /* loudness based on equal loudness curve; */ + /* use granule with maximum combined loudness */ + max_pow = gfc->loudness_sq[0][0]; + gr2_max = gfc->loudness_sq[1][0]; + if (gfc->channels_out == 2) { + max_pow += gfc->loudness_sq[0][1]; + gr2_max += gfc->loudness_sq[1][1]; + } + else { + max_pow += max_pow; + gr2_max += gr2_max; + } + if (gfc->mode_gr == 2) { + max_pow = Max(max_pow, gr2_max); + } + max_pow *= 0.5; /* max_pow approaches 1.0 for full band noise */ + + /* jd - 2001 mar 31, jun 30 */ + /* user tuning of ATH adjustment region */ + max_pow *= gfc->ATH->aa_sensitivity_p; + + /* adjust ATH depending on range of maximum value + */ + + /* jd - 2001 feb27, mar12,20, jun30, jul22 */ + /* continuous curves based on approximation */ + /* to GB's original values. */ + /* For an increase in approximate loudness, */ + /* set ATH adjust to adjust_limit immediately */ + /* after a delay of one frame. */ + /* For a loudness decrease, reduce ATH adjust */ + /* towards adjust_limit gradually. */ + /* max_pow is a loudness squared or a power. */ + if (max_pow > 0.03125) { /* ((1 - 0.000625)/ 31.98) from curve below */ + if (gfc->ATH->adjust >= 1.0) { + gfc->ATH->adjust = 1.0; + } + else { + /* preceding frame has lower ATH adjust; */ + /* ascend only to the preceding adjust_limit */ + /* in case there is leading low volume */ + if (gfc->ATH->adjust < gfc->ATH->adjust_limit) { + gfc->ATH->adjust = gfc->ATH->adjust_limit; + } + } + gfc->ATH->adjust_limit = 1.0; + } + else { /* adjustment curve */ + /* about 32 dB maximum adjust (0.000625) */ + FLOAT const adj_lim_new = 31.98 * max_pow + 0.000625; + if (gfc->ATH->adjust >= adj_lim_new) { /* descend gradually */ + gfc->ATH->adjust *= adj_lim_new * 0.075 + 0.925; + if (gfc->ATH->adjust < adj_lim_new) { /* stop descent */ + gfc->ATH->adjust = adj_lim_new; + } + } + else { /* ascend */ + if (gfc->ATH->adjust_limit >= adj_lim_new) { + gfc->ATH->adjust = adj_lim_new; + } + else { /* preceding frame has lower ATH adjust; */ + /* ascend only to the preceding adjust_limit */ + if (gfc->ATH->adjust < gfc->ATH->adjust_limit) { + gfc->ATH->adjust = gfc->ATH->adjust_limit; + } + } + } + gfc->ATH->adjust_limit = adj_lim_new; + } +} + +/*********************************************************************** + * + * some simple statistics + * + * bitrate index 0: free bitrate -> not allowed in VBR mode + * : bitrates, kbps depending on MPEG version + * bitrate index 15: forbidden + * + * mode_ext: + * 0: LR + * 1: LR-i + * 2: MS + * 3: MS-i + * + ***********************************************************************/ + +static void +updateStats(lame_internal_flags * const gfc) +{ + int gr, ch; + assert(0 <= gfc->bitrate_index && gfc->bitrate_index < 16); + assert(0 <= gfc->mode_ext && gfc->mode_ext < 4); + + /* count bitrate indices */ + gfc->bitrate_stereoMode_Hist[gfc->bitrate_index][4]++; + gfc->bitrate_stereoMode_Hist[15][4]++; + + /* count 'em for every mode extension in case of 2 channel encoding */ + if (gfc->channels_out == 2) { + gfc->bitrate_stereoMode_Hist[gfc->bitrate_index][gfc->mode_ext]++; + gfc->bitrate_stereoMode_Hist[15][gfc->mode_ext]++; + } + for (gr = 0; gr < gfc->mode_gr; ++gr) { + for (ch = 0; ch < gfc->channels_out; ++ch) { + int bt = gfc->l3_side.tt[gr][ch].block_type; + if (gfc->l3_side.tt[gr][ch].mixed_block_flag) + bt = 4; + gfc->bitrate_blockType_Hist[gfc->bitrate_index][bt]++; + gfc->bitrate_blockType_Hist[gfc->bitrate_index][5]++; + gfc->bitrate_blockType_Hist[15][bt]++; + gfc->bitrate_blockType_Hist[15][5]++; + } + } +} + + + + +static void +lame_encode_frame_init(lame_global_flags const *const gfp, const sample_t * inbuf[2]) +{ + lame_internal_flags *const gfc = gfp->internal_flags; + + int ch, gr; + + if (gfc->lame_encode_frame_init == 0) { + /* prime the MDCT/polyphase filterbank with a short block */ + int i, j; + sample_t primebuff0[286 + 1152 + 576]; + sample_t primebuff1[286 + 1152 + 576]; + gfc->lame_encode_frame_init = 1; + for (i = 0, j = 0; i < 286 + 576 * (1 + gfc->mode_gr); ++i) { + if (i < 576 * gfc->mode_gr) { + primebuff0[i] = 0; + if (gfc->channels_out == 2) + primebuff1[i] = 0; + } + else { + primebuff0[i] = inbuf[0][j]; + if (gfc->channels_out == 2) + primebuff1[i] = inbuf[1][j]; + ++j; + } + } + /* polyphase filtering / mdct */ + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + gfc->l3_side.tt[gr][ch].block_type = SHORT_TYPE; + } + } + mdct_sub48(gfc, primebuff0, primebuff1); + + /* check FFT will not use a negative starting offset */ +#if 576 < FFTOFFSET +# error FFTOFFSET greater than 576: FFT uses a negative offset +#endif + /* check if we have enough data for FFT */ + assert(gfc->mf_size >= (BLKSIZE + gfp->framesize - FFTOFFSET)); + /* check if we have enough data for polyphase filterbank */ + assert(gfc->mf_size >= (512 + gfp->framesize - 32)); + } + +} + + + + + + + +/************************************************************************ +* +* encodeframe() Layer 3 +* +* encode a single frame +* +************************************************************************ +lame_encode_frame() + + + gr 0 gr 1 +inbuf: |--------------|--------------|--------------| + + +Polyphase (18 windows, each shifted 32) +gr 0: +window1 <----512----> +window18 <----512----> + +gr 1: +window1 <----512----> +window18 <----512----> + + + +MDCT output: |--------------|--------------|--------------| + +FFT's <---------1024----------> + <---------1024--------> + + + + inbuf = buffer of PCM data size=MP3 framesize + encoder acts on inbuf[ch][0], but output is delayed by MDCTDELAY + so the MDCT coefficints are from inbuf[ch][-MDCTDELAY] + + psy-model FFT has a 1 granule delay, so we feed it data for the + next granule. + FFT is centered over granule: 224+576+224 + So FFT starts at: 576-224-MDCTDELAY + + MPEG2: FFT ends at: BLKSIZE+576-224-MDCTDELAY (1328) + MPEG1: FFT ends at: BLKSIZE+2*576-224-MDCTDELAY (1904) + + MPEG2: polyphase first window: [0..511] + 18th window: [544..1055] (1056) + MPEG1: 36th window: [1120..1631] (1632) + data needed: 512+framesize-32 + + A close look newmdct.c shows that the polyphase filterbank + only uses data from [0..510] for each window. Perhaps because the window + used by the filterbank is zero for the last point, so Takehiro's + code doesn't bother to compute with it. + + FFT starts at 576-224-MDCTDELAY (304) = 576-FFTOFFSET + +*/ + +typedef FLOAT chgrdata[2][2]; + + +int +lame_encode_mp3_frame( /* Output */ + lame_global_flags * const gfp, /* Context */ + sample_t const *inbuf_l, /* Input */ + sample_t const *inbuf_r, /* Input */ + unsigned char *mp3buf, /* Output */ + int mp3buf_size) +{ /* Output */ + int mp3count; + III_psy_ratio masking_LR[2][2]; /*LR masking & energy */ + III_psy_ratio masking_MS[2][2]; /*MS masking & energy */ + III_psy_ratio(*masking)[2][2]; /*pointer to selected maskings */ + const sample_t *inbuf[2]; + lame_internal_flags *const gfc = gfp->internal_flags; + + FLOAT tot_ener[2][4]; + FLOAT ms_ener_ratio[2] = { .5, .5 }; + chgrdata pe = { {0., 0.}, {0., 0.} }, pe_MS = { { + 0., 0.}, { + 0., 0.}}; + chgrdata *pe_use; + + int ch, gr; + + inbuf[0] = inbuf_l; + inbuf[1] = inbuf_r; + + if (gfc->lame_encode_frame_init == 0) { + /*first run? */ + lame_encode_frame_init(gfp, inbuf); + + } + + + /********************** padding *****************************/ + /* padding method as described in + * "MPEG-Layer3 / Bitstream Syntax and Decoding" + * by Martin Sieler, Ralph Sperschneider + * + * note: there is no padding for the very first frame + * + * Robert Hegemann 2000-06-22 + */ + gfc->padding = FALSE; + if ((gfc->slot_lag -= gfc->frac_SpF) < 0) { + gfc->slot_lag += gfp->out_samplerate; + gfc->padding = TRUE; + } + + + + /**************************************** + * Stage 1: psychoacoustic model * + ****************************************/ + + if (gfc->psymodel) { + /* psychoacoustic model + * psy model has a 1 granule (576) delay that we must compensate for + * (mt 6/99). + */ + int ret; + const sample_t *bufp[2]; /* address of beginning of left & right granule */ + int blocktype[2]; + + for (gr = 0; gr < gfc->mode_gr; gr++) { + + for (ch = 0; ch < gfc->channels_out; ch++) { + bufp[ch] = &inbuf[ch][576 + gr * 576 - FFTOFFSET]; + } + if (gfp->VBR == vbr_mtrh || gfp->VBR == vbr_mt) { + ret = L3psycho_anal_vbr(gfp, bufp, gr, + masking_LR, masking_MS, + pe[gr], pe_MS[gr], tot_ener[gr], blocktype); + } + else { + ret = L3psycho_anal_ns(gfp, bufp, gr, + masking_LR, masking_MS, + pe[gr], pe_MS[gr], tot_ener[gr], blocktype); + } + if (ret != 0) + return -4; + + if (gfp->mode == JOINT_STEREO) { + ms_ener_ratio[gr] = tot_ener[gr][2] + tot_ener[gr][3]; + if (ms_ener_ratio[gr] > 0) + ms_ener_ratio[gr] = tot_ener[gr][3] / ms_ener_ratio[gr]; + } + + /* block type flags */ + for (ch = 0; ch < gfc->channels_out; ch++) { + gr_info *const cod_info = &gfc->l3_side.tt[gr][ch]; + cod_info->block_type = blocktype[ch]; + cod_info->mixed_block_flag = 0; + } + } + } + else { + /*no psy model */ + memset((char *) masking_LR, 0, sizeof(masking_LR)); + memset((char *) masking_MS, 0, sizeof(masking_MS)); + for (gr = 0; gr < gfc->mode_gr; gr++) + for (ch = 0; ch < gfc->channels_out; ch++) { + gfc->l3_side.tt[gr][ch].block_type = NORM_TYPE; + gfc->l3_side.tt[gr][ch].mixed_block_flag = 0; + pe_MS[gr][ch] = pe[gr][ch] = 700; + } + } + + + + /* auto-adjust of ATH, useful for low volume */ + adjust_ATH(gfc); + + + /**************************************** + * Stage 2: MDCT * + ****************************************/ + + /* polyphase filtering / mdct */ + mdct_sub48(gfc, inbuf[0], inbuf[1]); + + + /**************************************** + * Stage 3: MS/LR decision * + ****************************************/ + + /* Here will be selected MS or LR coding of the 2 stereo channels */ + gfc->mode_ext = MPG_MD_LR_LR; + + if (gfp->force_ms) { + gfc->mode_ext = MPG_MD_MS_LR; + } + else if (gfp->mode == JOINT_STEREO) { + /* ms_ratio = is scaled, for historical reasons, to look like + a ratio of side_channel / total. + 0 = signal is 100% mono + .5 = L & R uncorrelated + */ + + /* [0] and [1] are the results for the two granules in MPEG-1, + * in MPEG-2 it's only a faked averaging of the same value + * _prev is the value of the last granule of the previous frame + * _next is the value of the first granule of the next frame + */ + + FLOAT sum_pe_MS = 0; + FLOAT sum_pe_LR = 0; + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + sum_pe_MS += pe_MS[gr][ch]; + sum_pe_LR += pe[gr][ch]; + } + } + + /* based on PE: M/S coding would not use much more bits than L/R */ + if (sum_pe_MS <= 1.00 * sum_pe_LR) { + + gr_info const *const gi0 = &gfc->l3_side.tt[0][0]; + gr_info const *const gi1 = &gfc->l3_side.tt[gfc->mode_gr - 1][0]; + + if (gi0[0].block_type == gi0[1].block_type && gi1[0].block_type == gi1[1].block_type) { + + gfc->mode_ext = MPG_MD_MS_LR; + } + } + } + + /* bit and noise allocation */ + if (gfc->mode_ext == MPG_MD_MS_LR) { + masking = &masking_MS; /* use MS masking */ + pe_use = &pe_MS; + } + else { + masking = &masking_LR; /* use LR masking */ + pe_use = &pe; + } + + + /* copy data for MP3 frame analyzer */ + if (gfp->analysis && gfc->pinfo != NULL) { + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + gfc->pinfo->ms_ratio[gr] = gfc->ms_ratio[gr]; + gfc->pinfo->ms_ener_ratio[gr] = ms_ener_ratio[gr]; + gfc->pinfo->blocktype[gr][ch] = gfc->l3_side.tt[gr][ch].block_type; + gfc->pinfo->pe[gr][ch] = (*pe_use)[gr][ch]; + memcpy(gfc->pinfo->xr[gr][ch], &gfc->l3_side.tt[gr][ch].xr[0], sizeof(FLOAT) * 576); + /* in psymodel, LR and MS data was stored in pinfo. + switch to MS data: */ + if (gfc->mode_ext == MPG_MD_MS_LR) { + gfc->pinfo->ers[gr][ch] = gfc->pinfo->ers[gr][ch + 2]; + memcpy(gfc->pinfo->energy[gr][ch], gfc->pinfo->energy[gr][ch + 2], + sizeof(gfc->pinfo->energy[gr][ch])); + } + } + } + } + + + /**************************************** + * Stage 4: quantization loop * + ****************************************/ + + if (gfp->VBR == vbr_off || gfp->VBR == vbr_abr) { + static FLOAT const fircoef[9] = { + -0.0207887 * 5, -0.0378413 * 5, -0.0432472 * 5, -0.031183 * 5, + 7.79609e-18 * 5, 0.0467745 * 5, 0.10091 * 5, 0.151365 * 5, + 0.187098 * 5 + }; + + int i; + FLOAT f; + + for (i = 0; i < 18; i++) + gfc->nsPsy.pefirbuf[i] = gfc->nsPsy.pefirbuf[i + 1]; + + f = 0.0; + for (gr = 0; gr < gfc->mode_gr; gr++) + for (ch = 0; ch < gfc->channels_out; ch++) + f += (*pe_use)[gr][ch]; + gfc->nsPsy.pefirbuf[18] = f; + + f = gfc->nsPsy.pefirbuf[9]; + for (i = 0; i < 9; i++) + f += (gfc->nsPsy.pefirbuf[i] + gfc->nsPsy.pefirbuf[18 - i]) * fircoef[i]; + + f = (670 * 5 * gfc->mode_gr * gfc->channels_out) / f; + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + (*pe_use)[gr][ch] *= f; + } + } + } + gfc->iteration_loop(gfp, *pe_use, ms_ener_ratio, *masking); + + + /**************************************** + * Stage 5: bitstream formatting * + ****************************************/ + + + /* write the frame to the bitstream */ + (void) format_bitstream(gfp); + + /* copy mp3 bit buffer into array */ + mp3count = copy_buffer(gfc, mp3buf, mp3buf_size, 1); + + + if (gfp->bWriteVbrTag) + AddVbrFrame(gfp); + + + if (gfp->analysis && gfc->pinfo != NULL) { + for (ch = 0; ch < gfc->channels_out; ch++) { + int j; + for (j = 0; j < FFTOFFSET; j++) + gfc->pinfo->pcmdata[ch][j] = gfc->pinfo->pcmdata[ch][j + gfp->framesize]; + for (j = FFTOFFSET; j < 1600; j++) { + gfc->pinfo->pcmdata[ch][j] = inbuf[ch][j - FFTOFFSET]; + } + } + set_frame_pinfo(gfp, *masking); + } + + updateStats(gfc); + + return mp3count; +} |