From: kramm Date: Sun, 28 Apr 2002 17:30:17 +0000 (+0000) Subject: initial revision X-Git-Tag: xpdf-0-92~12 X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=commitdiff_plain;h=698acf324aaa52147b1486646f6549ffd95804da initial revision --- diff --git a/lib/lame/VbrTag.c b/lib/lame/VbrTag.c new file mode 100644 index 0000000..c5ca217 --- /dev/null +++ b/lib/lame/VbrTag.c @@ -0,0 +1,944 @@ +/* + * Xing VBR tagging for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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: VbrTag.c,v 1.1 2002/04/28 17:30:17 kramm Exp $ */ + +#include "config_static.h" + +#include "machine.h" +#if defined(__riscos__) && defined(FPA10) +#include "ymath.h" +#else +#include +#endif + + +#include "bitstream.h" +#include "lame.h" +#include "VbrTag.h" +#include "version.h" + +#include +#include +#include + +#ifdef WITH_DMALLOC +#include +#endif + +#ifdef _DEBUG +/* #define DEBUG_VBRTAG */ +#endif + +/* +// 4 bytes for Header Tag +// 4 bytes for Header Flags +// 100 bytes for entry (NUMTOCENTRIES) +// 4 bytes for FRAME SIZE +// 4 bytes for STREAM_SIZE +// 4 bytes for VBR SCALE. a VBR quality indicator: 0=best 100=worst +// 20 bytes for LAME tag. for example, "LAME3.12 (beta 6)" +// ___________ +// 140 bytes +*/ +#define VBRHEADERSIZE (NUMTOCENTRIES+4+4+4+4+4) + +#define LAMEHEADERSIZE (VBRHEADERSIZE + 9 + 1 + 1 + 8 + 1 + 1 + 3 + 1 + 1 + 2 + 4 + 2 + 2) + +/* the size of the Xing header (MPEG1 and MPEG2) in kbps */ +#define XING_BITRATE1 128 +#define XING_BITRATE2 64 +#define XING_BITRATE25 32 + + + +const static char VBRTag[]={"Xing"}; +const static char VBRTag2[]={"Info"}; + + + + +/* Lookup table for fast CRC computation + * See 'CRC_update_lookup' + * Uses the polynomial x^16+x^15+x^2+1 */ + +unsigned int crc16_lookup[256] = +{ + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + + + + + +/*********************************************************************** + * Robert Hegemann 2001-01-17 + ***********************************************************************/ + +static void addVbr(VBR_seek_info_t * v, int bitrate) +{ + int i; + + v->sum += bitrate; + v->seen ++; + + if (v->seen < v->want) { + return; + } + + if (v->pos < v->size) { + v->bag[v->pos] = v->sum; + v->pos ++; + v->seen = 0; + } + if (v->pos == v->size) { + for (i = 1; i < v->size; i += 2) { + v->bag[i/2] = v->bag[i]; + } + v->want *= 2; + v->pos /= 2; + } +} + +static void Xing_seek_table(VBR_seek_info_t * v, unsigned char *t) +{ + int i, index; + int seek_point; + + if (v->pos <= 0) + return; + + for (i = 1; i < NUMTOCENTRIES; ++i) { + float j = i/(float)NUMTOCENTRIES, act, sum; + index = (int)(floor(j * v->pos)); + if (index > v->pos-1) + index = v->pos-1; + act = v->bag[index]; + sum = v->sum; + seek_point = (int)(256. * act / sum); + if (seek_point > 255) + seek_point = 255; + t[i] = seek_point; + } +} + +#if 0 +void print_seeking(unsigned char *t) +{ + int i; + + printf("seeking table "); + for (i = 0; i < NUMTOCENTRIES; ++i) { + printf(" %d ", t[i]); + } + printf("\n"); +} +#endif + + + +/**************************************************************************** + * AddVbrFrame: Add VBR entry, used to fill the VBR the TOC entries + * Paramters: + * nStreamPos: how many bytes did we write to the bitstream so far + * (in Bytes NOT Bits) + **************************************************************************** +*/ +void AddVbrFrame(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + + int kbps = bitrate_table[gfp->version][gfc->bitrate_index]; + + if (gfc->VBR_seek_table.bag == NULL) { + gfc->VBR_seek_table.sum = 0; + gfc->VBR_seek_table.seen = 0; + gfc->VBR_seek_table.want = 1; + gfc->VBR_seek_table.pos = 0; + gfc->VBR_seek_table.bag = malloc (400*sizeof(int)); + if (gfc->VBR_seek_table.bag != NULL) { + gfc->VBR_seek_table.size = 400; + } + else { + gfc->VBR_seek_table.size = 0; + ERRORF (gfc,"Error: can't allocate VbrFrames buffer\n"); + return; + } + } + addVbr(&gfc->VBR_seek_table, kbps); + gfp->nVbrNumFrames++; +} + + +/*-------------------------------------------------------------*/ +static int ExtractI4(unsigned char *buf) +{ + int x; + /* big endian extract */ + x = buf[0]; + x <<= 8; + x |= buf[1]; + x <<= 8; + x |= buf[2]; + x <<= 8; + x |= buf[3]; + return x; +} + +static void CreateI4(unsigned char *buf, int nValue) +{ + /* big endian create */ + buf[0]=(nValue>>24)&0xff; + buf[1]=(nValue>>16)&0xff; + buf[2]=(nValue>> 8)&0xff; + buf[3]=(nValue )&0xff; +} + + + +static void CreateI2(unsigned char *buf, int nValue) +{ + /* big endian create */ + buf[0]=(nValue>> 8)&0xff; + buf[1]=(nValue )&0xff; +} + + +/*-------------------------------------------------------------*/ +/* Same as GetVbrTag below, but only checks for the Xing tag. + requires buf to contain only 40 bytes */ +/*-------------------------------------------------------------*/ +int CheckVbrTag(unsigned char *buf) +{ + int h_id, h_mode, h_sr_index; + + /* get selected MPEG header data */ + h_id = (buf[1] >> 3) & 1; + h_sr_index = (buf[2] >> 2) & 3; + h_mode = (buf[3] >> 6) & 3; + + /* determine offset of header */ + if( h_id ) + { + /* mpeg1 */ + if( h_mode != 3 ) buf+=(32+4); + else buf+=(17+4); + } + else + { + /* mpeg2 */ + if( h_mode != 3 ) buf+=(17+4); + else buf+=(9+4); + } + + if( buf[0] != VBRTag[0] && buf[0] != VBRTag2[0] ) return 0; /* fail */ + if( buf[1] != VBRTag[1] && buf[1] != VBRTag2[1]) return 0; /* header not found*/ + if( buf[2] != VBRTag[2] && buf[2] != VBRTag2[2]) return 0; + if( buf[3] != VBRTag[3] && buf[3] != VBRTag2[3]) return 0; + return 1; +} + +int GetVbrTag(VBRTAGDATA *pTagData, unsigned char *buf) +{ + int i, head_flags; + int h_bitrate,h_id, h_mode, h_sr_index; + int enc_delay,enc_padding; + + /* get Vbr header data */ + pTagData->flags = 0; + + /* get selected MPEG header data */ + h_id = (buf[1] >> 3) & 1; + h_sr_index = (buf[2] >> 2) & 3; + h_mode = (buf[3] >> 6) & 3; + h_bitrate = ((buf[2]>>4)&0xf); + h_bitrate = bitrate_table[h_id][h_bitrate]; + + /* check for FFE syncword */ + if ((buf[1]>>4)==0xE) + pTagData->samprate = samplerate_table[2][h_sr_index]; + else + pTagData->samprate = samplerate_table[h_id][h_sr_index]; + // if( h_id == 0 ) + // pTagData->samprate >>= 1; + + + + /* determine offset of header */ + if( h_id ) + { + /* mpeg1 */ + if( h_mode != 3 ) buf+=(32+4); + else buf+=(17+4); + } + else + { + /* mpeg2 */ + if( h_mode != 3 ) buf+=(17+4); + else buf+=(9+4); + } + + if( buf[0] != VBRTag[0] && buf[0] != VBRTag2[0] ) return 0; /* fail */ + if( buf[1] != VBRTag[1] && buf[1] != VBRTag2[1]) return 0; /* header not found*/ + if( buf[2] != VBRTag[2] && buf[2] != VBRTag2[2]) return 0; + if( buf[3] != VBRTag[3] && buf[3] != VBRTag2[3]) return 0; + + buf+=4; + + pTagData->h_id = h_id; + + head_flags = pTagData->flags = ExtractI4(buf); buf+=4; /* get flags */ + + if( head_flags & FRAMES_FLAG ) + { + pTagData->frames = ExtractI4(buf); buf+=4; + } + + if( head_flags & BYTES_FLAG ) + { + pTagData->bytes = ExtractI4(buf); buf+=4; + } + + if( head_flags & TOC_FLAG ) + { + if( pTagData->toc != NULL ) + { + for(i=0;itoc[i] = buf[i]; + } + buf+=NUMTOCENTRIES; + } + + pTagData->vbr_scale = -1; + + if( head_flags & VBR_SCALE_FLAG ) + { + pTagData->vbr_scale = ExtractI4(buf); buf+=4; + } + + pTagData->headersize = + ((h_id+1)*72000*h_bitrate) / pTagData->samprate; + + buf+=21; + enc_delay = buf[0] << 4; + enc_delay += buf[1] >> 4; + enc_padding= (buf[1] & 0x0F)<<8; + enc_padding += buf[2]; + // check for reasonable values (this may be an old Xing header, + // not a INFO tag) + if (enc_delay<0 || enc_delay > 3000) enc_delay=-1; + if (enc_padding<0 || enc_padding > 3000) enc_padding=-1; + + pTagData->enc_delay=enc_delay; + pTagData->enc_padding=enc_padding; + +#ifdef DEBUG_VBRTAG + fprintf(stderr,"\n\n********************* VBR TAG INFO *****************\n"); + fprintf(stderr,"tag :%s\n",VBRTag); + fprintf(stderr,"head_flags :%d\n",head_flags); + fprintf(stderr,"bytes :%d\n",pTagData->bytes); + fprintf(stderr,"frames :%d\n",pTagData->frames); + fprintf(stderr,"VBR Scale :%d\n",pTagData->vbr_scale); + fprintf(stderr,"enc_delay = %i \n",enc_delay); + fprintf(stderr,"enc_padding= %i \n",enc_padding); + fprintf(stderr,"toc:\n"); + if( pTagData->toc != NULL ) + { + for(i=0;itoc[i])); + } + } + fprintf(stderr,"\n***************** END OF VBR TAG INFO ***************\n"); +#endif + return 1; /* success */ +} + + +/**************************************************************************** + * InitVbrTag: Initializes the header, and write empty frame to stream + * Paramters: + * fpStream: pointer to output file stream + * nMode : Channel Mode: 0=STEREO 1=JS 2=DS 3=MONO + **************************************************************************** +*/ +int InitVbrTag(lame_global_flags *gfp) +{ + int nMode,SampIndex; + lame_internal_flags *gfc = gfp->internal_flags; +#define MAXFRAMESIZE 2880 // or 0xB40, the max freeformat 640 32kHz framesize + // uint8_t pbtStreamBuffer[MAXFRAMESIZE]; + nMode = gfp->mode; + SampIndex = gfc->samplerate_index; + + + /* Clear Frame position array variables */ + //gfp->pVbrFrames=NULL; + gfp->nVbrNumFrames=0; + gfp->nVbrFrameBufferSize=0; + + + /* Clear stream buffer */ + // memset(pbtStreamBuffer,0x00,sizeof(pbtStreamBuffer)); + + + + /* + // Xing VBR pretends to be a 48kbs layer III frame. (at 44.1kHz). + // (at 48kHz they use 56kbs since 48kbs frame not big enough for + // table of contents) + // let's always embed Xing header inside a 64kbs layer III frame. + // this gives us enough room for a LAME version string too. + // size determined by sampling frequency (MPEG1) + // 32kHz: 216 bytes@48kbs 288bytes@ 64kbs + // 44.1kHz: 156 bytes 208bytes@64kbs (+1 if padding = 1) + // 48kHz: 144 bytes 192 + // + // MPEG 2 values are the same since the framesize and samplerate + // are each reduced by a factor of 2. + */ + { + int i,bitrate,tot; + if (1==gfp->version) { + bitrate = XING_BITRATE1; + } else { + if (gfp->out_samplerate < 16000 ) + bitrate = XING_BITRATE25; + else + bitrate = XING_BITRATE2; + } + + if (gfp->VBR==vbr_off) + bitrate = gfp->brate; + + gfp->TotalFrameSize= + ((gfp->version+1)*72000*bitrate) / gfp->out_samplerate; + + tot = (gfc->sideinfo_len+LAMEHEADERSIZE); + + if (gfp->TotalFrameSize < tot || + gfp->TotalFrameSize > MAXFRAMESIZE ) { + // disable tag, it wont fit + gfp->bWriteVbrTag = 0; + return 0; + } + + for (i=0; iTotalFrameSize; ++i) + add_dummy_byte(gfp,0); + } + + /* Success */ + return 0; +} + + + +/* fast CRC-16 computation - uses table crc16_lookup 8*/ +int CRC_update_lookup(int value, int crc) +{ + int tmp; + tmp=crc^value; + crc=(crc>>8)^crc16_lookup[tmp & 0xff]; + return crc; +} + +void UpdateMusicCRC(uint16_t *crc,unsigned char *buffer, int size){ + int i; + for (i=0; ibWriteVbrTag) + return; + + if (nStart) + MSGF( gfp->internal_flags, "Writing LAME Tag..."); + else + MSGF( gfp->internal_flags, "done\n"); + +} + + +/**************************************************************************** + * Jonathan Dee 2001/08/31 + * + * PutLameVBR: Write LAME info: mini version + info on various switches used + * Paramters: + * pbtStreamBuffer : pointer to output buffer + * id3v2size : size of id3v2 tag in bytes + * crc : computation of crc-16 of Lame Tag so far (starting at frame sync) + * + **************************************************************************** +*/ +int PutLameVBR(lame_global_flags *gfp, FILE *fpStream, uint8_t *pbtStreamBuffer, uint32_t id3v2size, uint16_t crc) +{ + lame_internal_flags *gfc = gfp->internal_flags; +// FLOAT fVersion = LAME_MAJOR_VERSION + 0.01 * LAME_MINOR_VERSION; + + int nBytesWritten = 0; + int nFilesize = 0; //size of fpStream. Will be equal to size after process finishes. + int i; + + int enc_delay=lame_get_encoder_delay(gfp); // encoder delay + int enc_padding=lame_get_encoder_padding(gfp); // encoder padding + + //recall: gfp->VBR_q is for example set by the switch -V + // gfp->quality by -q, -h, -f, etc + + int nQuality = (100 - 10 * gfp->VBR_q - gfp->quality); + + + const char *szVersion = get_lame_very_short_version(); + uint8_t nVBR; + uint8_t nRevision = 0x00; + uint8_t nRevMethod; + uint8_t vbr_type_translator[] = {1,5,3,2,4,0,3}; //numbering different in vbr_mode vs. Lame tag + + uint8_t nLowpass = ( ((gfp->lowpassfreq / 100.0)+.5) > 255 ? 255 : (gfp->lowpassfreq / 100.0)+.5 ); + + ieee754_float32_t fPeakSignalAmplitude = 0; //TODO... + uint16_t nRadioReplayGain = 0; //TODO... + uint16_t nAudioPhileReplayGain = 0; //TODO... + + + + + uint8_t nNoiseShaping = gfp->internal_flags->noise_shaping; + uint8_t nStereoMode = 0; + int bNonOptimal = 0; + uint8_t nSourceFreq = 0; + uint8_t nMisc = 0; + uint32_t nMusicLength = 0; + int bId3v1Present = ((gfp->internal_flags->tag_spec.flags & CHANGED_FLAG) + && !(gfp->internal_flags->tag_spec.flags & V2_ONLY_FLAG)); + uint16_t nMusicCRC = 0; + + //psy model type: Gpsycho or NsPsytune + unsigned char bExpNPsyTune = gfp->exp_nspsytune & 1; + unsigned char bSafeJoint = (gfp->exp_nspsytune & 2)!=0; + + unsigned char bNoGapMore = 0; + unsigned char bNoGapPrevious = 0; + + int nNoGapCount = gfp->internal_flags->nogap_total; + int nNoGapCurr = gfp->internal_flags->nogap_current; + + + uint8_t nAthType = gfp->ATHtype; //4 bits. + + uint8_t nFlags = 0; + + // if ABR, {store bitrate <=255} else { store "-b"} + int nABRBitrate = (gfp->VBR==vbr_abr)?gfp->VBR_mean_bitrate_kbps:gfp->brate; + + //revision and vbr method + if (gfp->VBR>=0 && gfp->VBR < sizeof(vbr_type_translator)) + nVBR = vbr_type_translator[gfp->VBR]; + else + nVBR = 0x00; //unknown. + + nRevMethod = 0x10 * nRevision + nVBR; + + //nogap + if (nNoGapCount != -1) + { + if (nNoGapCurr > 0) + bNoGapPrevious = 1; + + if (nNoGapCurr < nNoGapCount-1) + bNoGapMore = 1; + } + + //flags + + nFlags = nAthType + (bExpNPsyTune << 4) + + (bSafeJoint << 5) + + (bNoGapMore << 6) + + (bNoGapPrevious << 7); + + + if (nQuality < 0) + nQuality = 0; + + /*stereo mode field... a bit ugly.*/ + + switch(gfp->mode) + { + case MONO: + nStereoMode = 0; + break; + case STEREO: + nStereoMode = 1; + break; + case DUAL_CHANNEL: + nStereoMode = 2; + break; + case JOINT_STEREO: + if (gfp->force_ms) + nStereoMode = 4; + else + nStereoMode = 3; + break; + case NOT_SET: + /* FALLTHROUGH */ + default: + nStereoMode = 7; + break; + } + + if (gfp->mode_automs) + nStereoMode = 5; + + /*Intensity stereo : nStereoMode = 6. IS is not implemented */ + + if (gfp->in_samplerate <= 32000) + nSourceFreq = 0x00; + else if (gfp->in_samplerate ==48000) + nSourceFreq = 0x02; + else if (gfp->in_samplerate > 48000) + nSourceFreq = 0x03; + else + nSourceFreq = 0x01; //default is 44100Hz. + + + //Check if the user overrided the default LAME behaviour with some nasty options + + if (gfp->short_blocks == short_block_forced || + gfp->short_blocks == short_block_dispensed || + ((gfp->lowpassfreq == -1) && (gfp->highpassfreq == -1)) || // "-k" + (gfp->scale_left != gfp->scale_right) || + gfp->disable_reservoir || + gfp->noATH || + gfp->ATHonly || + (nAthType == 0) || + gfp->in_samplerate <= 32000) + bNonOptimal = 1; + + nMisc = nNoiseShaping + + (nStereoMode << 2) + + (bNonOptimal << 5) + + (nSourceFreq << 6); + + + + //get filesize + fseek(fpStream, 0, SEEK_END); + nFilesize = ftell(fpStream); + + + nMusicLength = nFilesize - id3v2size; //omit current frame + if (bId3v1Present) + nMusicLength-=128; //id3v1 present. + nMusicCRC = gfc->nMusicCRC; + + + /*Write all this information into the stream*/ + CreateI4(&pbtStreamBuffer[nBytesWritten], nQuality); + nBytesWritten+=4; + + strncpy(&pbtStreamBuffer[nBytesWritten], szVersion, 9); + nBytesWritten+=9; + + pbtStreamBuffer[nBytesWritten] = nRevMethod ; + nBytesWritten++; + + pbtStreamBuffer[nBytesWritten] = nLowpass; + nBytesWritten++; + + memmove(&pbtStreamBuffer[nBytesWritten], &fPeakSignalAmplitude, 4); + nBytesWritten+=4; + + CreateI2(&pbtStreamBuffer[nBytesWritten],nRadioReplayGain); + nBytesWritten+=2; + + CreateI2(&pbtStreamBuffer[nBytesWritten],nAudioPhileReplayGain); + nBytesWritten+=2; + + pbtStreamBuffer[nBytesWritten] = nFlags; + nBytesWritten++; + + if (nABRBitrate >= 255) + pbtStreamBuffer[nBytesWritten] = 0xFF; + else + pbtStreamBuffer[nBytesWritten] = nABRBitrate; + nBytesWritten++; + + pbtStreamBuffer[nBytesWritten ] = enc_delay >> 4; // works for win32, does it for unix? + pbtStreamBuffer[nBytesWritten +1] = (enc_delay << 4) + (enc_padding >> 8); + pbtStreamBuffer[nBytesWritten +2] = enc_padding; + + nBytesWritten+=3; + + pbtStreamBuffer[nBytesWritten] = nMisc; + nBytesWritten++; + + + memset(pbtStreamBuffer+nBytesWritten,0, 3); //unused in rev0 + nBytesWritten+=3; + + CreateI4(&pbtStreamBuffer[nBytesWritten], nMusicLength); + nBytesWritten+=4; + + CreateI2(&pbtStreamBuffer[nBytesWritten], nMusicCRC); + nBytesWritten+=2; + + /*Calculate tag CRC.... must be done here, since it includes + *previous information*/ + + for (i = 0;iinternal_flags; + + long lFileSize; + int nStreamIndex; + char abyte,bbyte; + uint8_t btToc[NUMTOCENTRIES]; + uint8_t pbtStreamBuffer[MAXFRAMESIZE]; + + int i; + uint16_t crc = 0x00; + + unsigned char id3v2Header[10]; + size_t id3v2TagSize; + + if (gfc->VBR_seek_table.pos <= 0) + return -1; + + + /* Clear stream buffer */ + memset(pbtStreamBuffer,0x00,sizeof(pbtStreamBuffer)); + + /* Seek to end of file*/ + fseek(fpStream,0,SEEK_END); + + /* Get file size */ + lFileSize=ftell(fpStream); + + /* Abort if file has zero length. Yes, it can happen :) */ + if (lFileSize==0) + return -1; + + /* + * The VBR tag may NOT be located at the beginning of the stream. + * If an ID3 version 2 tag was added, then it must be skipped to write + * the VBR tag data. + */ + + /* seek to the beginning of the stream */ + fseek(fpStream,0,SEEK_SET); + /* read 10 bytes in case there's an ID3 version 2 header here */ + fread(id3v2Header,1,sizeof id3v2Header,fpStream); + /* does the stream begin with the ID3 version 2 file identifier? */ + if (!strncmp((char *)id3v2Header,"ID3",3)) { + /* the tag size (minus the 10-byte header) is encoded into four + * bytes where the most significant bit is clear in each byte */ + id3v2TagSize=(((id3v2Header[6] & 0x7f)<<21) + | ((id3v2Header[7] & 0x7f)<<14) + | ((id3v2Header[8] & 0x7f)<<7) + | (id3v2Header[9] & 0x7f)) + + sizeof id3v2Header; + } else { + /* no ID3 version 2 tag in this stream */ + id3v2TagSize=0; + } + + /* Seek to first real frame */ + fseek(fpStream,id3v2TagSize+gfp->TotalFrameSize,SEEK_SET); + + /* Read the header (first valid frame) */ + fread(pbtStreamBuffer,4,1,fpStream); + + /* the default VBR header. 48 kbps layer III, no padding, no crc */ + /* but sampling freq, mode andy copyright/copy protection taken */ + /* from first valid frame */ + pbtStreamBuffer[0]=(uint8_t) 0xff; + abyte = (pbtStreamBuffer[1] & (char) 0xf1); + { + int bitrate; + if (1==gfp->version) { + bitrate = XING_BITRATE1; + } else { + if (gfp->out_samplerate < 16000 ) + bitrate = XING_BITRATE25; + else + bitrate = XING_BITRATE2; + } + + if (gfp->VBR==vbr_off) + bitrate = gfp->brate; + + bbyte = 16*BitrateIndex(bitrate,gfp->version,gfp->out_samplerate); + } + + /* Use as much of the info from the real frames in the + * Xing header: samplerate, channels, crc, etc... + */ + if (gfp->version==1) { + /* MPEG1 */ + pbtStreamBuffer[1]=abyte | (char) 0x0a; /* was 0x0b; */ + abyte = pbtStreamBuffer[2] & (char) 0x0d; /* AF keep also private bit */ + pbtStreamBuffer[2]=(char) bbyte | abyte; /* 64kbs MPEG1 frame */ + }else{ + /* MPEG2 */ + pbtStreamBuffer[1]=abyte | (char) 0x02; /* was 0x03; */ + abyte = pbtStreamBuffer[2] & (char) 0x0d; /* AF keep also private bit */ + pbtStreamBuffer[2]=(char) bbyte | abyte; /* 64kbs MPEG2 frame */ + } + + /* Clear all TOC entries */ + memset(btToc,0,sizeof(btToc)); + + Xing_seek_table (&gfc->VBR_seek_table, btToc); + /* print_seeking (btToc); */ + + /* Start writing the tag after the zero frame */ + nStreamIndex=gfc->sideinfo_len; + /* note! Xing header specifies that Xing data goes in the + * ancillary data with NO ERROR PROTECTION. If error protecton + * in enabled, the Xing data still starts at the same offset, + * and now it is in sideinfo data block, and thus will not + * decode correctly by non-Xing tag aware players */ + if (gfp->error_protection) nStreamIndex -= 2; + + /* Put Vbr tag */ + if (gfp->VBR == vbr_off) + { + pbtStreamBuffer[nStreamIndex++]=VBRTag2[0]; + pbtStreamBuffer[nStreamIndex++]=VBRTag2[1]; + pbtStreamBuffer[nStreamIndex++]=VBRTag2[2]; + pbtStreamBuffer[nStreamIndex++]=VBRTag2[3]; + + } + else + { + pbtStreamBuffer[nStreamIndex++]=VBRTag[0]; + pbtStreamBuffer[nStreamIndex++]=VBRTag[1]; + pbtStreamBuffer[nStreamIndex++]=VBRTag[2]; + pbtStreamBuffer[nStreamIndex++]=VBRTag[3]; + } + + /* Put header flags */ + CreateI4(&pbtStreamBuffer[nStreamIndex],FRAMES_FLAG+BYTES_FLAG+TOC_FLAG+VBR_SCALE_FLAG); + nStreamIndex+=4; + + /* Put Total Number of frames */ + CreateI4(&pbtStreamBuffer[nStreamIndex],gfp->nVbrNumFrames); + nStreamIndex+=4; + + /* Put Total file size */ + CreateI4(&pbtStreamBuffer[nStreamIndex],(int)lFileSize); + nStreamIndex+=4; + + /* Put TOC */ + memcpy(&pbtStreamBuffer[nStreamIndex],btToc,sizeof(btToc)); + nStreamIndex+=sizeof(btToc); + + + if (gfp->error_protection) { + /* (jo) error_protection: add crc16 information to header */ + CRC_writeheader(gfc, pbtStreamBuffer); + } + + + + //work out CRC so far: initially crc = 0 + for (i = 0;i< nStreamIndex ;i++) + crc = CRC_update_lookup(pbtStreamBuffer[i], crc); + + /*Put LAME VBR info*/ + nStreamIndex+=PutLameVBR(gfp, fpStream, pbtStreamBuffer + nStreamIndex, id3v2TagSize,crc); + +#ifdef DEBUG_VBRTAG + { + VBRTAGDATA TestHeader; + GetVbrTag(&TestHeader,pbtStreamBuffer); + } +#endif + + /*Seek to the beginning of the stream */ + fseek(fpStream,id3v2TagSize,SEEK_SET); + + /* Put it all to disk again */ + if (fwrite(pbtStreamBuffer,(unsigned int)gfp->TotalFrameSize,1,fpStream)!=1) + { + return -1; + } + /* Save to delete the frame buffer */ + //free(gfp->pVbrFrames); see HACKING for instructions on how + //gfp->pVbrFrames=NULL; memory in 'gfp' is allocated/free'd + + return 0; /* success */ +} + diff --git a/lib/lame/VbrTag.h b/lib/lame/VbrTag.h new file mode 100644 index 0000000..f7d14d3 --- /dev/null +++ b/lib/lame/VbrTag.h @@ -0,0 +1,80 @@ +/* + * Xing VBR tagging for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_VRBTAG_H +#define LAME_VRBTAG_H +#include "lame.h" +/* ----------------------------------------------------------- + * A Vbr header may be present in the ancillary + * data field of the first frame of an mp3 bitstream + * The Vbr header (optionally) contains + * frames total number of audio frames in the bitstream + * bytes total number of bytes in the bitstream + * toc table of contents + + * toc (table of contents) gives seek points + * for random access + * the ith entry determines the seek point for + * i-percent duration + * seek point in bytes = (toc[i]/256.0) * total_bitstream_bytes + * e.g. half duration seek point = (toc[50]/256.0) * total_bitstream_bytes + */ + + +#define FRAMES_FLAG 0x0001 +#define BYTES_FLAG 0x0002 +#define TOC_FLAG 0x0004 +#define VBR_SCALE_FLAG 0x0008 + +#define NUMTOCENTRIES 100 + +#define FRAMES_AND_BYTES (FRAMES_FLAG | BYTES_FLAG) + + + +/*structure to receive extracted header */ +/* toc may be NULL*/ +typedef struct +{ + int h_id; /* from MPEG header, 0=MPEG2, 1=MPEG1 */ + int samprate; /* determined from MPEG header */ + int flags; /* from Vbr header data */ + int frames; /* total bit stream frames from Vbr header data */ + int bytes; /* total bit stream bytes from Vbr header data*/ + int vbr_scale; /* encoded vbr scale from Vbr header data*/ + unsigned char toc[NUMTOCENTRIES]; /* may be NULL if toc not desired*/ + int headersize; /* size of VBR header, in bytes */ + int enc_delay; /* encoder delay */ + int enc_padding; /* encoder paddign added at end of stream */ +} VBRTAGDATA; + +int CheckVbrTag(unsigned char *buf); +int GetVbrTag(VBRTAGDATA *pTagData, unsigned char *buf); + +int SeekPoint(unsigned char TOC[NUMTOCENTRIES], int file_bytes, float percent); +int InitVbrTag(lame_global_flags *gfp); +int PutVbrTag(lame_global_flags *gfp,FILE *fid,int nVbrScale); +int PutLameVBR(lame_global_flags *gfp, FILE *fpStream, uint8_t *pbtStreamBuffer, uint32_t id3v2size, uint16_t crc); +void AddVbrFrame(lame_global_flags *gfp); +void ReportLameTagProgress(lame_global_flags *gfp,int nStart); +void UpdateMusicCRC(uint16_t *crc,unsigned char *buffer, int size); + +#endif diff --git a/lib/lame/bitstream.c b/lib/lame/bitstream.c new file mode 100644 index 0000000..fda431d --- /dev/null +++ b/lib/lame/bitstream.c @@ -0,0 +1,977 @@ +/* + * MP3 bitstream Output interface for LAME + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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: bitstream.c,v 1.1 2002/04/28 17:30:17 kramm Exp $ + */ + + +#include "config_static.h" + +#include +#include +#include +#include "tables.h" +#include "bitstream.h" +#include "quantize.h" +#include "quantize_pvt.h" +#include "version.h" +#include "VbrTag.h" + +#ifdef WITH_DMALLOC +#include +#endif + +/* This is the scfsi_band table from 2.4.2.7 of the IS */ +const int scfsi_band[5] = { 0, 6, 11, 16, 21 }; + + +/* unsigned int is at least this large: */ +/* we work with ints, so when doing bit manipulation, we limit + * ourselves to MAX_LENGTH-2 just to be on the safe side */ +#define MAX_LENGTH 32 + + + +#ifdef DEBUG +static int hoge, hogege; +#endif + + + + + +void putheader_bits(lame_internal_flags *gfc,int w_ptr) +{ + Bit_stream_struc *bs; + bs = &gfc->bs; +#ifdef DEBUG + hoge += gfc->sideinfo_len * 8; + hogege += gfc->sideinfo_len * 8; +#endif + memcpy(&bs->buf[bs->buf_byte_idx], gfc->header[gfc->w_ptr].buf, + gfc->sideinfo_len); + bs->buf_byte_idx += gfc->sideinfo_len; + bs->totbit += gfc->sideinfo_len * 8; + gfc->w_ptr = (gfc->w_ptr + 1) & (MAX_HEADER_BUF - 1); +} + + + + +/*write j bits into the bit stream */ +inline static void +putbits2(lame_global_flags *gfp, int val, int j) +{ + lame_internal_flags *gfc=gfp->internal_flags; + Bit_stream_struc *bs; + bs = &gfc->bs; + + assert(j < MAX_LENGTH-2); + + while (j > 0) { + int k; + if (bs->buf_bit_idx == 0) { + bs->buf_bit_idx = 8; + bs->buf_byte_idx++; + assert(bs->buf_byte_idx < BUFFER_SIZE); + assert(gfc->header[gfc->w_ptr].write_timing >= bs->totbit); + if (gfc->header[gfc->w_ptr].write_timing == bs->totbit) { + putheader_bits(gfc,gfc->w_ptr); + } + bs->buf[bs->buf_byte_idx] = 0; + } + + k = Min(j, bs->buf_bit_idx); + j -= k; + + bs->buf_bit_idx -= k; + + assert (j < MAX_LENGTH); /* 32 too large on 32 bit machines */ + assert (bs->buf_bit_idx < MAX_LENGTH); + + bs->buf[bs->buf_byte_idx] |= ((val >> j) << bs->buf_bit_idx); + bs->totbit += k; + } +} + +/*write j bits into the bit stream, ignoring frame headers */ +inline static void +putbits_noheaders(lame_global_flags *gfp, int val, int j) +{ + lame_internal_flags *gfc=gfp->internal_flags; + Bit_stream_struc *bs; + bs = &gfc->bs; + + assert(j < MAX_LENGTH-2); + + while (j > 0) { + int k; + if (bs->buf_bit_idx == 0) { + bs->buf_bit_idx = 8; + bs->buf_byte_idx++; + assert(bs->buf_byte_idx < BUFFER_SIZE); + bs->buf[bs->buf_byte_idx] = 0; + } + + k = Min(j, bs->buf_bit_idx); + j -= k; + + bs->buf_bit_idx -= k; + + assert (j < MAX_LENGTH); /* 32 too large on 32 bit machines */ + assert (bs->buf_bit_idx < MAX_LENGTH); + + bs->buf[bs->buf_byte_idx] |= ((val >> j) << bs->buf_bit_idx); + bs->totbit += k; + } +} + + +/* + Some combinations of bitrate, Fs, and stereo make it impossible to stuff + out a frame using just main_data, due to the limited number of bits to + indicate main_data_length. In these situations, we put stuffing bits into + the ancillary data... +*/ + +inline static void +drain_into_ancillary(lame_global_flags *gfp,int remainingBits) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int i; + assert(remainingBits >= 0); + + if (remainingBits >= 8) { + putbits2(gfp,0x4c,8); + remainingBits -= 8; + } + if (remainingBits >= 8) { + putbits2(gfp,0x41,8); + remainingBits -= 8; + } + if (remainingBits >= 8) { + putbits2(gfp,0x4d,8); + remainingBits -= 8; + } + if (remainingBits >= 8) { + putbits2(gfp,0x45,8); + remainingBits -= 8; + } + + if (remainingBits >= 32) { + const char *version = get_lame_short_version (); + if (remainingBits >= 32) + for (i=0; i<(int)strlen(version) && remainingBits >=8 ; ++i) { + remainingBits -= 8; + putbits2(gfp,version[i],8); + } + } + + for (; remainingBits >= 1; remainingBits -= 1 ) { + putbits2 ( gfp, gfc->ancillary_flag, 1 ); + gfc->ancillary_flag ^= 1; + } + + assert (remainingBits == 0); + +} + +/*write N bits into the header */ +inline static void +writeheader(lame_internal_flags *gfc,int val, int j) +{ + int ptr = gfc->header[gfc->h_ptr].ptr; + + while (j > 0) { + int k = Min(j, 8 - (ptr & 7)); + j -= k; + assert (j < MAX_LENGTH); /* >> 32 too large for 32 bit machines */ + gfc->header[gfc->h_ptr].buf[ptr >> 3] + |= ((val >> j)) << (8 - (ptr & 7) - k); + ptr += k; + } + gfc->header[gfc->h_ptr].ptr = ptr; +} + + +static int +CRC_update(int value, int crc) +{ + int i; + value <<= 8; + for (i = 0; i < 8; i++) { + value <<= 1; + crc <<= 1; + + if (((crc ^ value) & 0x10000)) + crc ^= CRC16_POLYNOMIAL; + } + return crc; +} + + +void +CRC_writeheader(lame_internal_flags *gfc, char *header) +{ + int crc = 0xffff; /* (jo) init crc16 for error_protection */ + int i; + + crc = CRC_update(((unsigned char*)header)[2], crc); + crc = CRC_update(((unsigned char*)header)[3], crc); + for (i = 6; i < gfc->sideinfo_len; i++) { + crc = CRC_update(((unsigned char*)header)[i], crc); + } + + header[4] = crc >> 8; + header[5] = crc & 255; +} + +inline static void +encodeSideInfo2(lame_global_flags *gfp,int bitsPerFrame) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_side_info_t *l3_side; + int gr, ch; + + l3_side = &gfc->l3_side; + gfc->header[gfc->h_ptr].ptr = 0; + memset(gfc->header[gfc->h_ptr].buf, 0, gfc->sideinfo_len); + if (gfp->out_samplerate < 16000) + writeheader(gfc,0xffe, 12); + else + writeheader(gfc,0xfff, 12); + writeheader(gfc,(gfp->version), 1); + writeheader(gfc,4 - 3, 2); + writeheader(gfc,(!gfp->error_protection), 1); + writeheader(gfc,(gfc->bitrate_index), 4); + writeheader(gfc,(gfc->samplerate_index), 2); + writeheader(gfc,(gfc->padding), 1); + writeheader(gfc,(gfp->extension), 1); + writeheader(gfc,(gfp->mode), 2); + writeheader(gfc,(gfc->mode_ext), 2); + writeheader(gfc,(gfp->copyright), 1); + writeheader(gfc,(gfp->original), 1); + writeheader(gfc,(gfp->emphasis), 2); + if (gfp->error_protection) { + writeheader(gfc,0, 16); /* dummy */ + } + + if (gfp->version == 1) { + /* MPEG1 */ + assert(l3_side->main_data_begin >= 0); + writeheader(gfc,(l3_side->main_data_begin), 9); + + if (gfc->channels_out == 2) + writeheader(gfc,l3_side->private_bits, 3); + else + writeheader(gfc,l3_side->private_bits, 5); + + for (ch = 0; ch < gfc->channels_out; ch++) { + int band; + for (band = 0; band < 4; band++) { + writeheader(gfc,l3_side->scfsi[ch][band], 1); + } + } + + for (gr = 0; gr < 2; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + gr_info *gi = &l3_side->gr[gr].ch[ch].tt; + writeheader(gfc,gi->part2_3_length, 12); + writeheader(gfc,gi->big_values / 2, 9); + writeheader(gfc,gi->global_gain, 8); + writeheader(gfc,gi->scalefac_compress, 4); + writeheader(gfc,gi->window_switching_flag, 1); + + if (gi->window_switching_flag) { + writeheader(gfc,gi->block_type, 2); + writeheader(gfc,gi->mixed_block_flag, 1); + + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc,gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc,gi->table_select[1], 5); + + writeheader(gfc,gi->subblock_gain[0], 3); + writeheader(gfc,gi->subblock_gain[1], 3); + writeheader(gfc,gi->subblock_gain[2], 3); + } else { + assert(gi->block_type == NORM_TYPE); + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc,gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc,gi->table_select[1], 5); + if (gi->table_select[2] == 14) + gi->table_select[2] = 16; + writeheader(gfc,gi->table_select[2], 5); + + assert(gi->region0_count < 16U); + assert(gi->region1_count < 8U); + writeheader(gfc,gi->region0_count, 4); + writeheader(gfc,gi->region1_count, 3); + } + writeheader(gfc,gi->preflag, 1); + writeheader(gfc,gi->scalefac_scale, 1); + writeheader(gfc,gi->count1table_select, 1); + } + } + } else { + /* MPEG2 */ + assert(l3_side->main_data_begin >= 0); + writeheader(gfc,(l3_side->main_data_begin), 8); + writeheader(gfc,l3_side->private_bits, gfc->channels_out); + + gr = 0; + for (ch = 0; ch < gfc->channels_out; ch++) { + gr_info *gi = &l3_side->gr[gr].ch[ch].tt; + writeheader(gfc,gi->part2_3_length, 12); + writeheader(gfc,gi->big_values / 2, 9); + writeheader(gfc,gi->global_gain, 8); + writeheader(gfc,gi->scalefac_compress, 9); + writeheader(gfc,gi->window_switching_flag, 1); + + if (gi->window_switching_flag) { + writeheader(gfc,gi->block_type, 2); + writeheader(gfc,gi->mixed_block_flag, 1); + + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc,gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc,gi->table_select[1], 5); + + writeheader(gfc,gi->subblock_gain[0], 3); + writeheader(gfc,gi->subblock_gain[1], 3); + writeheader(gfc,gi->subblock_gain[2], 3); + } else { + if (gi->table_select[0] == 14) + gi->table_select[0] = 16; + writeheader(gfc,gi->table_select[0], 5); + if (gi->table_select[1] == 14) + gi->table_select[1] = 16; + writeheader(gfc,gi->table_select[1], 5); + if (gi->table_select[2] == 14) + gi->table_select[2] = 16; + writeheader(gfc,gi->table_select[2], 5); + + assert(gi->region0_count < 16U); + assert(gi->region1_count < 8U); + writeheader(gfc,gi->region0_count, 4); + writeheader(gfc,gi->region1_count, 3); + } + + writeheader(gfc,gi->scalefac_scale, 1); + writeheader(gfc,gi->count1table_select, 1); + } + } + + if (gfp->error_protection) { + /* (jo) error_protection: add crc16 information to header */ + CRC_writeheader(gfc, gfc->header[gfc->h_ptr].buf); + } + + { + int old = gfc->h_ptr; + assert(gfc->header[old].ptr == gfc->sideinfo_len * 8); + + gfc->h_ptr = (old + 1) & (MAX_HEADER_BUF - 1); + gfc->header[gfc->h_ptr].write_timing = + gfc->header[old].write_timing + bitsPerFrame; + + if (gfc->h_ptr == gfc->w_ptr) { + /* yikes! we are out of header buffer space */ + ERRORF(gfc,"Error: MAX_HEADER_BUF too small in bitstream.c \n"); + } + + } +} + + +inline static int +huffman_coder_count1(lame_global_flags *gfp,int *ix, gr_info *gi) +{ +#ifdef DEBUG + lame_internal_flags *gfc = gfp->internal_flags; +#endif + /* Write count1 area */ + const struct huffcodetab *h = &ht[gi->count1table_select + 32]; + int i,bits=0; +#ifdef DEBUG + int gegebo = gfc->bs.totbit; +#endif + + ix += gi->big_values; + assert(gi->count1table_select < 2); + + + for (i = (gi->count1 - gi->big_values) / 4; i > 0; --i) { + int huffbits = 0; + int p = 0, v; + + v = ix[0]; + if (v) { + p += 8; + if (v < 0) + huffbits++; + assert(-1 <= v && v <= 1); + } + + v = ix[1]; + if (v) { + p += 4; + huffbits *= 2; + if (v < 0) + huffbits++; + assert(-1 <= v && v <= 1); + } + + v = ix[2]; + if (v) { + p += 2; + huffbits *= 2; + if (v < 0) + huffbits++; + assert(-1 <= v && v <= 1); + } + + v = ix[3]; + if (v) { + p++; + huffbits *= 2; + if (v < 0) + huffbits++; + assert(-1 <= v && v <= 1); + } + + ix += 4; + putbits2(gfp,huffbits + h->table[p], h->hlen[p]); + bits += h->hlen[p]; + } +#ifdef DEBUG + DEBUGF(gfc,"%ld %d %d %d\n",gfc->bs.totbit -gegebo, gi->count1bits, gi->big_values, gi->count1); +#endif + return bits; +} + + + +/* + Implements the pseudocode of page 98 of the IS + */ + +inline static int +HuffmanCode ( lame_global_flags* const gfp, const int table_select, int x1, int x2 ) +{ + const struct huffcodetab* h = ht + table_select; + int code = 0; + int cbits = 0; + int xbits = 0; + int sgn_x1 = 0; + int sgn_x2 = 0; + int linbits = h->xlen; + int xlen = h->xlen; + int ext; + + assert ( table_select > 0 ); + + if (x1 < 0) { + sgn_x1++; + x1 = -x1; + } + + if (x2 < 0) { + sgn_x2++; + x2 = -x2; + } + + ext = sgn_x1; + + if (table_select > 15) { + /* use ESC-words */ + if (x1 > 14) { + int linbits_x1 = x1 - 15; + assert ( linbits_x1 <= h->linmax ); + ext |= linbits_x1 << 1; + xbits = linbits; + x1 = 15; + } + + if (x2 > 14) { + int linbits_x2 = x2 - 15; + assert ( linbits_x2 <= h->linmax ); + ext <<= linbits; + ext |= linbits_x2; + xbits += linbits; + x2 = 15; + } + xlen = 16; + } + + if (x1 != 0) { + cbits--; + } + + if (x2 != 0) { + ext <<= 1; + ext |= sgn_x2; + cbits--; + } + + xbits -= cbits; + + assert ( (x1|x2) < 16u ); + + x1 = x1 * xlen + x2; + + code = h->table [x1]; + cbits += h->hlen [x1]; + + assert ( cbits <= MAX_LENGTH ); + assert ( xbits <= MAX_LENGTH ); + + putbits2 ( gfp, code, cbits ); + putbits2 ( gfp, ext, xbits ); + + return cbits + xbits; +} + +static int +Huffmancodebits(lame_global_flags *gfp, int tableindex, int start, int end, int *ix) +{ + int i,bits; + + assert(tableindex < 32); + if (!tableindex) return 0; + + bits=0; + for (i = start; i < end; i += 2) { + bits +=HuffmanCode(gfp,tableindex, ix[i], ix[i + 1]); + } + return bits; +} + + + +/* + Note the discussion of huffmancodebits() on pages 28 + and 29 of the IS, as well as the definitions of the side + information on pages 26 and 27. + */ +static int +ShortHuffmancodebits(lame_global_flags *gfp,int *ix, gr_info *gi) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int bits; + int region1Start; + + region1Start = 3*gfc->scalefac_band.s[3]; + if (region1Start > gi->big_values) + region1Start = gi->big_values; + + /* short blocks do not have a region2 */ + bits = Huffmancodebits(gfp,gi->table_select[0], 0, region1Start, ix); + bits += Huffmancodebits(gfp,gi->table_select[1], region1Start, gi->big_values, ix); + return bits; +} + +static int +LongHuffmancodebits(lame_global_flags *gfp,int *ix, gr_info *gi) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int i, bigvalues,bits=0; + int region1Start, region2Start; + + bigvalues = gi->big_values; + assert(0 <= bigvalues && bigvalues <= 576); + + i = gi->region0_count + 1; + assert(i < 23); + region1Start = gfc->scalefac_band.l[i]; + i += gi->region1_count + 1; + assert(i < 23); + region2Start = gfc->scalefac_band.l[i]; + + if (region1Start > bigvalues) + region1Start = bigvalues; + + if (region2Start > bigvalues) + region2Start = bigvalues; + + bits +=Huffmancodebits(gfp,gi->table_select[0], 0, region1Start, ix); + bits +=Huffmancodebits(gfp,gi->table_select[1], region1Start, region2Start, ix); + bits +=Huffmancodebits(gfp,gi->table_select[2], region2Start, bigvalues, ix); + return bits; +} + +inline static int +writeMainData ( lame_global_flags * const gfp, + int l3_enc [2] [2] [576], + III_scalefac_t scalefac [2] [2] ) +{ + int gr, ch, sfb,data_bits,scale_bits,tot_bits=0; + lame_internal_flags *gfc=gfp->internal_flags; + III_side_info_t *l3_side; + + l3_side = &gfc->l3_side; + if (gfp->version == 1) { + /* MPEG 1 */ + for (gr = 0; gr < 2; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + gr_info *gi = &l3_side->gr[gr].ch[ch].tt; + int slen1 = slen1_tab[gi->scalefac_compress]; + int slen2 = slen2_tab[gi->scalefac_compress]; + data_bits=0; + scale_bits=0; + +#ifdef DEBUG + hogege = gfc->bs.totbit; +#endif + if (gi->block_type == SHORT_TYPE) { + for (sfb = 0; sfb < SBPSY_s; sfb++) { + int slen = sfb < 6 ? slen1 : slen2; + + assert(scalefac[gr][ch].s[sfb][0]>=0); + assert(scalefac[gr][ch].s[sfb][1]>=0); + assert(scalefac[gr][ch].s[sfb][2]>=0); + + putbits2(gfp,scalefac[gr][ch].s[sfb][0], slen); + putbits2(gfp,scalefac[gr][ch].s[sfb][1], slen); + putbits2(gfp,scalefac[gr][ch].s[sfb][2], slen); + scale_bits += 3*slen; + } + data_bits += ShortHuffmancodebits(gfp,l3_enc[gr][ch], gi); + } else { + int i; + for (i = 0; i < sizeof(scfsi_band) / sizeof(int) - 1; + i++) { + if (gr != 0 && l3_side->scfsi[ch][i]) + continue; + + for (sfb = scfsi_band[i]; sfb < scfsi_band[i + 1]; + sfb++) { + + assert(scalefac[gr][ch].l[sfb]>=0); + putbits2(gfp,scalefac[gr][ch].l[sfb], + sfb < 11 ? slen1 : slen2); + scale_bits += sfb < 11 ? slen1 : slen2; + } + } + data_bits +=LongHuffmancodebits(gfp,l3_enc[gr][ch], gi); + } + data_bits +=huffman_coder_count1(gfp,l3_enc[gr][ch], gi); +#ifdef DEBUG + DEBUGF(gfc,"<%ld> ", gfc->bs.totbit-hogege); +#endif + /* does bitcount in quantize.c agree with actual bit count?*/ + assert(data_bits==gi->part2_3_length-gi->part2_length); + assert(scale_bits==gi->part2_length); + tot_bits += scale_bits + data_bits; + + } /* for ch */ + } /* for gr */ + } else { + /* MPEG 2 */ + gr = 0; + for (ch = 0; ch < gfc->channels_out; ch++) { + gr_info *gi = &l3_side->gr[gr].ch[ch].tt; + int i, sfb_partition; + assert(gi->sfb_partition_table); + data_bits = 0; + scale_bits=0; + + sfb = 0; + sfb_partition = 0; + if (gi->block_type == SHORT_TYPE) { + for (; sfb_partition < 4; sfb_partition++) { + int sfbs = gi->sfb_partition_table[sfb_partition] / 3; + int slen = gi->slen[sfb_partition]; + for (i = 0; i < sfbs; i++, sfb++) { + putbits2(gfp,Max(scalefac[gr][ch].s[sfb][0], 0U), slen); + putbits2(gfp,Max(scalefac[gr][ch].s[sfb][1], 0U), slen); + putbits2(gfp,Max(scalefac[gr][ch].s[sfb][2], 0U), slen); + scale_bits += 3*slen; + } + } + data_bits += ShortHuffmancodebits(gfp,l3_enc[gr][ch], gi); + } else { + for (; sfb_partition < 4; sfb_partition++) { + int sfbs = gi->sfb_partition_table[sfb_partition]; + int slen = gi->slen[sfb_partition]; + for (i = 0; i < sfbs; i++, sfb++) { + putbits2(gfp,Max(scalefac[gr][ch].l[sfb], 0U), slen); + scale_bits += slen; + } + } + data_bits +=LongHuffmancodebits(gfp,l3_enc[gr][ch], gi); + } + data_bits +=huffman_coder_count1(gfp,l3_enc[gr][ch], gi); + + /* does bitcount in quantize.c agree with actual bit count?*/ + assert(data_bits==gi->part2_3_length-gi->part2_length); + assert(scale_bits==gi->part2_length); + tot_bits += scale_bits + data_bits; + } /* for ch */ + } /* for gf */ + return tot_bits; +} /* main_data */ + + + +/* compute the number of bits required to flush all mp3 frames + currently in the buffer. This should be the same as the + reservoir size. Only call this routine between frames - i.e. + only after all headers and data have been added to the buffer + by format_bitstream(). + + Also compute total_bits_output = + size of mp3 buffer (including frame headers which may not + have yet been send to the mp3 buffer) + + number of bits needed to flush all mp3 frames. + + total_bytes_output is the size of the mp3 output buffer if + lame_encode_flush_nogap() was called right now. + + */ +int +compute_flushbits( const lame_global_flags * gfp, int *total_bytes_output ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int flushbits,remaining_headers; + int bitsPerFrame, mean_bits; + int last_ptr,first_ptr; + first_ptr=gfc->w_ptr; /* first header to add to bitstream */ + last_ptr = gfc->h_ptr - 1; /* last header to add to bitstream */ + if (last_ptr==-1) last_ptr=MAX_HEADER_BUF-1; + + /* add this many bits to bitstream so we can flush all headers */ + flushbits = gfc->header[last_ptr].write_timing - gfc->bs.totbit; + *total_bytes_output=flushbits; + + if (flushbits >= 0) { + /* if flushbits >= 0, some headers have not yet been written */ + /* reduce flushbits by the size of the headers */ + remaining_headers= 1+last_ptr - first_ptr; + if (last_ptr < first_ptr) + remaining_headers= 1+last_ptr - first_ptr + MAX_HEADER_BUF; + flushbits -= remaining_headers*8*gfc->sideinfo_len; + } + + + /* finally, add some bits so that the last frame is complete + * these bits are not necessary to decode the last frame, but + * some decoders will ignore last frame if these bits are missing + */ + getframebits(gfp,&bitsPerFrame,&mean_bits); + flushbits += bitsPerFrame; + *total_bytes_output += bitsPerFrame; + // round up: + if (*total_bytes_output % 8) + *total_bytes_output = 1 + (*total_bytes_output/8); + else + *total_bytes_output = (*total_bytes_output/8); + *total_bytes_output += gfc->bs.buf_byte_idx + 1; + + + if (flushbits<0) { +#if 0 + /* if flushbits < 0, this would mean that the buffer looks like: + * (data...) last_header (data...) (extra data that should not be here...) + */ + DEBUGF(gfc,"last header write_timing = %i \n",gfc->header[last_ptr].write_timing); + DEBUGF(gfc,"first header write_timing = %i \n",gfc->header[first_ptr].write_timing); + DEBUGF(gfc,"bs.totbit: %i \n",gfc->bs.totbit); + DEBUGF(gfc,"first_ptr, last_ptr %i %i \n",first_ptr,last_ptr); + DEBUGF(gfc,"remaining_headers = %i \n",remaining_headers); + DEBUGF(gfc,"bitsperframe: %i \n",bitsPerFrame); + DEBUGF(gfc,"sidelen: %i \n",gfc->sideinfo_len); +#endif + ERRORF(gfc,"strange error flushing buffer ... \n"); + } + return flushbits; +} + + + +void +flush_bitstream(lame_global_flags *gfp) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_side_info_t *l3_side; + int nbytes; + int flushbits; + int bitsPerFrame, mean_bits; + int last_ptr,first_ptr; + first_ptr=gfc->w_ptr; /* first header to add to bitstream */ + last_ptr = gfc->h_ptr - 1; /* last header to add to bitstream */ + if (last_ptr==-1) last_ptr=MAX_HEADER_BUF-1; + l3_side = &gfc->l3_side; + + + if ((flushbits = compute_flushbits(gfp,&nbytes)) < 0) return; + drain_into_ancillary(gfp,flushbits); + + /* check that the 100% of the last frame has been written to bitstream */ + getframebits(gfp,&bitsPerFrame,&mean_bits); + assert (gfc->header[last_ptr].write_timing + bitsPerFrame == gfc->bs.totbit); + + /* we have padded out all frames with ancillary data, which is the + same as filling the bitreservoir with ancillary data, so : */ + gfc->ResvSize=0; + l3_side->main_data_begin = 0; + +} + + + + +void add_dummy_byte ( lame_global_flags* const gfp, unsigned char val ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int i; + + putbits_noheaders(gfp,val,8); + + for (i=0 ; i< MAX_HEADER_BUF ; ++i) + gfc->header[i].write_timing += 8; +} + + +/* + format_bitstream() + + This is called after a frame of audio has been quantized and coded. + It will write the encoded audio to the bitstream. Note that + from a layer3 encoder's perspective the bit stream is primarily + a series of main_data() blocks, with header and side information + inserted at the proper locations to maintain framing. (See Figure A.7 + in the IS). + */ +int +format_bitstream(lame_global_flags *gfp, int bitsPerFrame, + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int bits,nbytes; + III_side_info_t *l3_side; + l3_side = &gfc->l3_side; + + drain_into_ancillary(gfp,l3_side->resvDrain_pre); + + encodeSideInfo2(gfp,bitsPerFrame); + bits = 8*gfc->sideinfo_len; + bits+=writeMainData(gfp,l3_enc,scalefac); + drain_into_ancillary(gfp,l3_side->resvDrain_post); + bits += l3_side->resvDrain_post; + + l3_side->main_data_begin += (bitsPerFrame-bits)/8; + + /* compare number of bits needed to clear all buffered mp3 frames + * with what we think the resvsize is: */ + if (compute_flushbits(gfp,&nbytes) != gfc->ResvSize) { + ERRORF(gfc,"Internal buffer inconsistency. flushbits <> ResvSize"); + } + + + /* compare main_data_begin for the next frame with what we + * think the resvsize is: */ + if ((l3_side->main_data_begin * 8) != gfc->ResvSize ) { + ERRORF(gfc,"bit reservoir error: \n" + "l3_side->main_data_begin: %i \n" + "Resvoir size: %i \n" + "resv drain (post) %i \n" + "resv drain (pre) %i \n" + "header and sideinfo: %i \n" + "data bits: %i \n" + "total bits: %i (remainder: %i) \n" + "bitsperframe: %i \n", + + 8*l3_side->main_data_begin, + gfc->ResvSize, + l3_side->resvDrain_post, + l3_side->resvDrain_pre, + 8*gfc->sideinfo_len, + bits-l3_side->resvDrain_post-8*gfc->sideinfo_len, + bits, bits % 8, + bitsPerFrame + ); + + gfc->ResvSize = l3_side->main_data_begin*8; + }; + assert(gfc->bs.totbit % 8 == 0); + + if (gfc->bs.totbit > 1000000000 ) { + /* to avoid totbit overflow, (at 8h encoding at 128kbs) lets reset bit counter*/ + int i; + for (i=0 ; i< MAX_HEADER_BUF ; ++i) + gfc->header[i].write_timing -= gfc->bs.totbit; + gfc->bs.totbit=0; + } + + + return 0; +} + + + + + +/* copy data out of the internal MP3 bit buffer into a user supplied + unsigned char buffer. + + mp3data=0 indicates data in buffer is an id3tags and VBR tags + mp3data=1 data is real mp3 frame data. + + +*/ +int copy_buffer(lame_internal_flags *gfc,unsigned char *buffer,int size,int mp3data) +{ + Bit_stream_struc *bs=&gfc->bs; + int minimum = bs->buf_byte_idx + 1; + if (minimum <= 0) return 0; + if (size!=0 && minimum>size) return -1; /* buffer is too small */ + memcpy(buffer,bs->buf,minimum); + bs->buf_byte_idx = -1; + bs->buf_bit_idx = 0; + + if (mp3data) { + UpdateMusicCRC(&gfc->nMusicCRC,buffer,minimum); + } + return minimum; +} + + +void init_bit_stream_w(lame_internal_flags *gfc) +{ + gfc->bs.buf = (unsigned char *) malloc(BUFFER_SIZE); + gfc->bs.buf_size = BUFFER_SIZE; + + gfc->h_ptr = gfc->w_ptr = 0; + gfc->header[gfc->h_ptr].write_timing = 0; + gfc->bs.buf_byte_idx = -1; + gfc->bs.buf_bit_idx = 0; + gfc->bs.totbit = 0; +} + +/* end of bitstream.c */ diff --git a/lib/lame/bitstream.h b/lib/lame/bitstream.h new file mode 100644 index 0000000..9ff1dbc --- /dev/null +++ b/lib/lame/bitstream.h @@ -0,0 +1,39 @@ +/* + * MP3 bitstream Output interface for LAME + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_BITSTREAM_H +#define LAME_BITSTREAM_H +#include "util.h" + +int format_bitstream(lame_global_flags *gfp, int i, + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2] ); + +void flush_bitstream(lame_global_flags *gfp); +void add_dummy_byte ( lame_global_flags* const gfp, unsigned char val ); + +int copy_buffer(lame_internal_flags *gfc,unsigned char *buffer,int buffer_size,int update_crc); +void init_bit_stream_w(lame_internal_flags *gfc); +void CRC_writeheader (lame_internal_flags *gfc, char *buffer); +int compute_flushbits(const lame_global_flags *gfp, int *nbytes); + + +#endif diff --git a/lib/lame/config_static.h b/lib/lame/config_static.h new file mode 100644 index 0000000..62c24ff --- /dev/null +++ b/lib/lame/config_static.h @@ -0,0 +1,124 @@ +/* Define if you have alloca, as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define if you have and it should be used (not on Ultrix). */ +#define HAVE_ALLOCA_H 1 + +/* Define if the `long double' type works. */ +#define HAVE_LONG_DOUBLE 1 + +/* Define to `unsigned' if doesn't define. */ +/* #undef size_t */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define if your processor stores words with the most significant + byte first (like Motorola and SPARC, unlike Intel and VAX). */ +/* #undef WORDS_BIGENDIAN */ + +/* #undef int8_t */ +#define uint8_t unsigned char +/* #undef int18_t */ +#define uint16_t unsigned short +/* #undef int32_t */ +#define uint32_t unsigned int +/* #undef int64_t */ +#define uint64_t unsigned long long +#define ieee854_float80_t long double +#define ieee754_float64_t double +#define ieee754_float32_t float + +/* The number of bytes in a double. */ +#define SIZEOF_DOUBLE 8 + +/* The number of bytes in a float. */ +#define SIZEOF_FLOAT 4 + +/* The number of bytes in a int. */ +#define SIZEOF_INT 4 + +/* The number of bytes in a long. */ +#define SIZEOF_LONG 4 + +/* The number of bytes in a long double. */ +/* #undef SIZEOF_LONG_DOUBLE */ + +/* The number of bytes in a long long. */ +#define SIZEOF_LONG_LONG 8 + +/* The number of bytes in a short. */ +#define SIZEOF_SHORT 2 + +/* The number of bytes in a unsigned int. */ +#define SIZEOF_UNSIGNED_INT 4 + +/* The number of bytes in a unsigned long. */ +#define SIZEOF_UNSIGNED_LONG 4 + +/* The number of bytes in a unsigned long long. */ +#define SIZEOF_UNSIGNED_LONG_LONG 8 + +/* The number of bytes in a unsigned short. */ +#define SIZEOF_UNSIGNED_SHORT 2 + +/* Define if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define if you have the header file. */ +#define HAVE_TERMCAP_H 1 + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Name of package */ +#define PACKAGE "lame" + +/* Version number of package */ +#define VERSION "3.91" + +/* Define if compiler has function prototypes */ +#define PROTOTYPES 1 + +/* system has 80 bit floats */ +#define HAVE_IEEE854_FLOAT80 1 + +/* requested by Frank, seems to be temporary needed for a smooth transition */ +#define LAME_LIBRARY_BUILD 1 + +/* have working GTK */ +#define HAVE_GTK 1 + +/* build with layer 1 decoding */ +#define USE_LAYER_1 1 + +/* build with layer 2 decoding */ +#define USE_LAYER_2 1 + +/* enable VBR bitrate histogram */ +#define BRHIST 1 + +/* have termcap */ +#define HAVE_TERMCAP 1 + +/* IEEE754 compatible machine */ +#define TAKEHIRO_IEEE754_HACK 1 + +/* no debug build */ +#define NDEBUG 1 + diff --git a/lib/lame/encoder.c b/lib/lame/encoder.c new file mode 100644 index 0000000..6c41875 --- /dev/null +++ b/lib/lame/encoder.c @@ -0,0 +1,665 @@ +/* + * LAME MP3 encoding engine + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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.1 2002/04/28 17:30:18 kramm Exp $ */ + +#include "config_static.h" + +#include + +#include "lame.h" +#include "util.h" +#include "newmdct.h" +#include "psymodel.h" +#include "quantize.h" +#include "quantize_pvt.h" +#include "bitstream.h" +#include "VbrTag.h" +#include "vbrquantize.h" + +#ifdef WITH_DMALLOC +#include +#endif + + +/* + * auto-adjust of ATH, useful for low volume + * Gabriel Bouvigne 3 feb 2001 + * + * modifies some values in + * gfp->internal_flags->ATH + * (gfc->ATH) + */ +void +adjust_ATH( lame_global_flags* const gfp, + FLOAT8 tot_ener[2][4] ) +{ + lame_internal_flags* const gfc = gfp->internal_flags; + int gr, channel; + FLOAT max_pow, max_pow_alt; + FLOAT8 max_val; + + if (gfc->ATH->use_adjust == 0) { + gfc->ATH->adjust = 1.0; /* no adjustment */ + return; + } + + switch( gfp->athaa_loudapprox ) { + case 1: + /* flat approximation for loudness (squared) */ + max_pow = 0; + for ( gr = 0; gr < gfc->mode_gr; ++gr ) + for ( channel = 0; channel < gfc->channels_out; ++channel ) + max_pow = Max( max_pow, tot_ener[gr][channel] ); + max_pow *= 0.25/ 5.6e13; /* scale to 0..1 (5.6e13), and tune (0.25) */ + break; + + case 2: /* jd - 2001 mar 12, 27, jun 30 */ + { /* loudness based on equal loudness curve; */ + /* use granule with maximum combined loudness*/ + FLOAT gr2_max; + max_pow = gfc->loudness_sq[0][0]; + if( gfc->channels_out == 2 ) { + max_pow += gfc->loudness_sq[0][1]; + gr2_max = gfc->loudness_sq[1][0] + gfc->loudness_sq[1][1]; + } else { + gr2_max = gfc->loudness_sq[1][0]; + 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*/ + break; + } + + default: /* jd - 2001 mar 27, 31, jun 30 */ + /* no adaptive threshold */ + max_pow = 1.0 / gfc->athaa_sensitivity_p; + break; + } + + /* jd - 2001 mar 31, jun 30 */ + /* user tuning of ATH adjustment region */ + max_pow_alt = max_pow; + max_pow *= gfc->athaa_sensitivity_p; + if (gfc->presetTune.use) + max_pow_alt *= pow( 10.0, gfc->presetTune.athadjust_safe_athaasensitivity / -10.0 ); + + /* adjust ATH depending on range of maximum value + */ + switch ( gfc->ATH->use_adjust ) { + + case 1: + max_val = sqrt( max_pow ); /* GB's original code requires a maximum */ + max_val *= 32768; /* sample or loudness value up to 32768 */ + + /* by Gabriel Bouvigne */ + if (0.5 < max_val / 32768) { /* value above 50 % */ + gfc->ATH->adjust = 1.0; /* do not reduce ATH */ + } + else if (0.3 < max_val / 32768) { /* value above 30 % */ + gfc->ATH->adjust *= 0.955; /* reduce by ~0.2 dB */ + if (gfc->ATH->adjust < 0.3) /* but ~5 dB in maximum */ + gfc->ATH->adjust = 0.3; + } + else { /* value below 30 % */ + gfc->ATH->adjust *= 0.93; /* reduce by ~0.3 dB */ + if (gfc->ATH->adjust < 0.01) /* but 20 dB in maximum */ + gfc->ATH->adjust = 0.01; + } + break; + + case 2: + max_val = Min( max_pow, 1.0 ) * 32768; /* adapt for RH's adjust */ + + { /* by Robert Hegemann */ + /* this code reduces slowly the ATH (speed of 12 dB per second) + */ + FLOAT8 + //x = Max (640, 320*(int)(max_val/320)); + x = Max (32, 32*(int)(max_val/32)); + x = x/32768; + gfc->ATH->adjust *= gfc->ATH->decay; + if (gfc->ATH->adjust < x) /* but not more than f(x) dB */ + gfc->ATH->adjust = x; + } + break; + + case 3: + { /* jd - 2001 feb27, mar12,20, jun30, jul22 */ + /* continuous curves based on approximation */ + /* to GB's original values. */ + FLOAT8 adj_lim_new; + /* 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; + if (gfc->presetTune.use) { + if (max_pow_alt > gfc->presetTune.athadjust_safe_noiseshaping_thre) + gfc->presetTune.athadjust_safe_noiseshaping = 1; + else + gfc->presetTune.athadjust_safe_noiseshaping = 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; + if (gfc->presetTune.use) { + if (max_pow_alt > gfc->presetTune.athadjust_safe_noiseshaping_thre) + gfc->presetTune.athadjust_safe_noiseshaping = 1; + else + gfc->presetTune.athadjust_safe_noiseshaping = 0; + } + } + } + gfc->ATH->adjust_limit = 1.0; + } else { /* adjustment curve */ + /* about 32 dB maximum adjust (0.000625) */ + 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; + } + } + break; + + default: + gfc->ATH->adjust = 1.0; /* no adjustment */ + break; + } /* switch */ +} + +/************************************************************************ +* +* encodeframe() Layer 3 +* +* encode a single frame +* +************************************************************************ +lame_encode_frame() + + + gr 0 gr 1 +inbuf: |--------------|---------------|-------------| +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 + MPEG1: FFT ends at: BLKSIZE+2*576-224-MDCTDELAY (1904) + + FFT starts at 576-224-MDCTDELAY (304) = 576-FFTOFFSET + +*/ + +typedef FLOAT8 chgrdata[2][2]; + +int lame_encode_mp3_frame ( // Output + lame_global_flags* const gfp, // Context + sample_t* inbuf_l, // Input + sample_t* inbuf_r, // Input + unsigned char* mp3buf, // Output + int mp3buf_size ) // Output +{ +#ifdef macintosh /* PLL 14/04/2000 */ + static FLOAT8 xr[2][2][576]; + static int l3_enc[2][2][576]; +#else + FLOAT8 xr[2][2][576]; + int l3_enc[2][2][576]; +#endif + 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*/ + III_scalefac_t scalefac[2][2]; + const sample_t *inbuf[2]; + lame_internal_flags *gfc=gfp->internal_flags; + + FLOAT8 tot_ener[2][4]; + FLOAT8 ms_ener_ratio[2]={.5,.5}; + chgrdata pe,pe_MS; + chgrdata *pe_use; + + int ch,gr,mean_bits; + int bitsPerFrame; + + int check_ms_stereo; + FLOAT8 ms_ratio_next = 0.; + FLOAT8 ms_ratio_prev = 0.; + + + memset((char *) masking_LR, 0, sizeof(masking_LR)); + memset((char *) masking_MS, 0, sizeof(masking_MS)); + memset((char *) scalefac, 0, sizeof(scalefac)); + inbuf[0]=inbuf_l; + inbuf[1]=inbuf_r; + + check_ms_stereo = (gfp->mode == JOINT_STEREO); + gfc->mode_ext = MPG_MD_LR_LR; + + if (gfc->lame_encode_frame_init==0 ) { + gfc->lame_encode_frame_init=1; + + /* 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@gmx.de 2000-06-22 + */ + + gfc->frac_SpF = ((gfp->version+1)*72000L*gfp->brate) % gfp->out_samplerate; + gfc->slot_lag = gfc->frac_SpF; + + /* 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 */ + /* it needs 1152 samples + 286 samples ignored for one granule */ + /* 1152+576+286 samples for two granules */ + assert(gfc->mf_size>=(286+576*(1+gfc->mode_gr))); + + /* prime the MDCT/polyphase filterbank with a short block */ + { + int i,j; + sample_t primebuff0[286+1152+576]; + sample_t primebuff1[286+1152+576]; + 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.gr[gr].ch[ch].tt.block_type=SHORT_TYPE; + } + } + mdct_sub48(gfc, primebuff0, primebuff1, xr); + } + + iteration_init(gfp); + + /* prepare for ATH auto adjustment: + * we want to decrease the ATH by 12 dB per second + */ { + FLOAT8 frame_duration = 576. * gfc->mode_gr / gfp->out_samplerate; + gfc->ATH->decay = pow(10., -12./10. * frame_duration); + gfc->ATH->adjust = 0.01; /* minimum, for leading low loudness */ + gfc->ATH->adjust_limit = 1.0; /* on lead, allow adjust up to maximum */ + } + } + + + /********************** padding *****************************/ + switch (gfp->padding_type) { + case PAD_NO: + gfc->padding = FALSE; + break; + case PAD_ALL: + gfc->padding = TRUE; + break; + case PAD_ADJUST: + default: + if (gfp->VBR!=vbr_off) { + gfc->padding = FALSE; + } else { + if (gfp->disable_reservoir) { + gfc->padding = FALSE; + /* if the user specified --nores, dont very gfc->padding either */ + /* tiny changes in frac_SpF rounding will cause file differences */ + }else{ + /* 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@gmx.de 2000-06-22 + */ + + gfc->slot_lag -= gfc->frac_SpF; + if (gfc->slot_lag < 0) { + gfc->slot_lag += gfp->out_samplerate; + gfc->padding = TRUE; + } else { + gfc->padding = FALSE; + } + } /* reservoir enabled */ + } + } + + + 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]; + + ms_ratio_prev=gfc->ms_ratio[gfc->mode_gr-1]; + 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 (gfc->nsPsy.use) { + ret=L3psycho_anal_ns( gfp, bufp, gr, + &gfc->ms_ratio[gr],&ms_ratio_next, + masking_LR, masking_MS, + pe[gr],pe_MS[gr],tot_ener[gr],blocktype); + } else { + ret=L3psycho_anal( gfp, bufp, gr, + &gfc->ms_ratio[gr],&ms_ratio_next, + masking_LR, masking_MS, + pe[gr],pe_MS[gr],tot_ener[gr],blocktype); + } + if (ret!=0) return -4; + + for ( ch = 0; ch < gfc->channels_out; ch++ ) + gfc->l3_side.gr[gr].ch[ch].tt.block_type=blocktype[ch]; + + if (check_ms_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]; + } + + } + }else{ + for (gr=0; gr < gfc->mode_gr ; gr++) + for ( ch = 0; ch < gfc->channels_out; ch++ ) { + gfc->l3_side.gr[gr].ch[ch].tt.block_type=NORM_TYPE; + pe_MS[gr][ch]=pe[gr][ch]=700; + } + } + + + + /* auto-adjust of ATH, useful for low volume */ + adjust_ATH( gfp, tot_ener ); + + + + /* block type flags */ + for( gr = 0; gr < gfc->mode_gr; gr++ ) { + for ( ch = 0; ch < gfc->channels_out; ch++ ) { + gr_info *cod_info = &gfc->l3_side.gr[gr].ch[ch].tt; + cod_info->mixed_block_flag = 0; /* never used by this model */ + if (cod_info->block_type == NORM_TYPE ) + cod_info->window_switching_flag = 0; + else + cod_info->window_switching_flag = 1; + } + } + + + /* polyphase filtering / mdct */ + mdct_sub48(gfc, inbuf[0], inbuf[1], xr); + /* re-order the short blocks, for more efficient encoding below */ + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + gr_info *cod_info = &gfc->l3_side.gr[gr].ch[ch].tt; + if (cod_info->block_type==SHORT_TYPE) { + freorder(gfc->scalefac_band.s,xr[gr][ch]); + } + } + } + + + /* use m/s gfc->channels_out? */ + if (check_ms_stereo) { + int gr0 = 0, gr1 = gfc->mode_gr-1; + /* make sure block type is the same in each channel */ + check_ms_stereo = + (gfc->l3_side.gr[gr0].ch[0].tt.block_type==gfc->l3_side.gr[gr0].ch[1].tt.block_type) && + (gfc->l3_side.gr[gr1].ch[0].tt.block_type==gfc->l3_side.gr[gr1].ch[1].tt.block_type); + } + + /* Here will be selected MS or LR coding of the 2 stereo channels */ + + assert ( gfc->mode_ext == MPG_MD_LR_LR ); + gfc->mode_ext = MPG_MD_LR_LR; + + if (gfp->force_ms) { + gfc->mode_ext = MPG_MD_MS_LR; + } else if (check_ms_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 + */ + FLOAT8 ms_ratio_ave1; + FLOAT8 ms_ratio_ave2; + FLOAT8 threshold1 = 0.35; + FLOAT8 threshold2 = 0.45; + + /* take an average */ + if (gfc->mode_gr==1) { + /* MPEG2 - no second granule */ + ms_ratio_ave1 = 0.33 * ( gfc->ms_ratio[0] + ms_ratio_prev + ms_ratio_next ); + ms_ratio_ave2 = gfc->ms_ratio[0]; + }else{ + ms_ratio_ave1 = 0.25 * ( gfc->ms_ratio[0] + gfc->ms_ratio[1] + ms_ratio_prev + ms_ratio_next ); + ms_ratio_ave2 = 0.50 * ( gfc->ms_ratio[0] + gfc->ms_ratio[1] ); + } + + if (gfp->mode_automs) { + if ( gfp->compression_ratio < 11.025 ) { + /* 11.025 => 1, 6.3 => 0 */ + double thr = (gfp->compression_ratio - 6.3) / (11.025 - 6.3); + if (thr<0) thr=0; + threshold1 *= thr; + threshold2 *= thr; + } + } + + if ((ms_ratio_ave1 < threshold1 && ms_ratio_ave2 < threshold2) || gfc->nsPsy.use) { + int sum_pe_MS = 0; + int 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 coding */ + + if (sum_pe_MS <= 1.07 * sum_pe_LR && !gfc->nsPsy.use) gfc->mode_ext = MPG_MD_MS_LR; + if (sum_pe_MS <= 1.00 * sum_pe_LR && gfc->nsPsy.use) gfc->mode_ext = MPG_MD_MS_LR; + } + } + + +#if defined(HAVE_GTK) + /* 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.gr[gr].ch[ch].tt.block_type; + memcpy(gfc->pinfo->xr[gr][ch],xr[gr][ch],sizeof(xr[gr][ch])); + /* in psymodel, LR and MS data was stored in pinfo. + switch to MS data: */ + if (gfc->mode_ext==MPG_MD_MS_LR) { + gfc->pinfo->pe[gr][ch]=gfc->pinfo->pe[gr][ch+2]; + 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])); + } + } + } + } +#endif + + + + + /* bit and noise allocation */ + if (MPG_MD_MS_LR == gfc->mode_ext) { + masking = &masking_MS; /* use MS masking */ + pe_use = &pe_MS; + } else { + masking = &masking_LR; /* use LR masking */ + pe_use = &pe; + } + + + if (gfc->nsPsy.use && (gfp->VBR == vbr_off || gfp->VBR == vbr_abr)) { + static FLOAT fircoef[19] = { + -0.0207887,-0.0378413,-0.0432472,-0.031183, + 7.79609e-18,0.0467745,0.10091,0.151365, + 0.187098,0.2,0.187098,0.151365, + 0.10091,0.0467745,7.79609e-18,-0.031183, + -0.0432472,-0.0378413,-0.0207887, + }; + int i; + FLOAT8 f; + + for(i=0;i<18;i++) gfc->nsPsy.pefirbuf[i] = gfc->nsPsy.pefirbuf[i+1]; + + i=0; + gfc->nsPsy.pefirbuf[18] = 0; + for ( gr = 0; gr < gfc->mode_gr; gr++ ) { + for ( ch = 0; ch < gfc->channels_out; ch++ ) { + gfc->nsPsy.pefirbuf[18] += (*pe_use)[gr][ch]; + i++; + } + } + + gfc->nsPsy.pefirbuf[18] = gfc->nsPsy.pefirbuf[18] / i; + f = 0; + for(i=0;i<19;i++) f += gfc->nsPsy.pefirbuf[i] * fircoef[i]; + + for ( gr = 0; gr < gfc->mode_gr; gr++ ) { + for ( ch = 0; ch < gfc->channels_out; ch++ ) { + (*pe_use)[gr][ch] *= 670 / f; + } + } + } + + switch (gfp->VBR){ + default: + case vbr_off: + iteration_loop( gfp,*pe_use,ms_ener_ratio, xr, *masking, l3_enc, scalefac); + break; + case vbr_mt: + VBR_quantize( gfp,*pe_use,ms_ener_ratio, xr, *masking, l3_enc, scalefac); + break; + case vbr_rh: + case vbr_mtrh: + VBR_iteration_loop( gfp,*pe_use,ms_ener_ratio, xr, *masking, l3_enc, scalefac); + break; + case vbr_abr: + ABR_iteration_loop( gfp,*pe_use,ms_ener_ratio, xr, *masking, l3_enc, scalefac); + break; + } + + /* write the frame to the bitstream */ + getframebits(gfp, &bitsPerFrame, &mean_bits); + + format_bitstream( gfp, bitsPerFrame, l3_enc, scalefac); + + /* copy mp3 bit buffer into array */ + mp3count = copy_buffer(gfc,mp3buf,mp3buf_size,1); + + + + + if (gfp->bWriteVbrTag) AddVbrFrame(gfp); + + +#if defined(HAVE_GTK) + /* copy data for MP3 frame analyzer */ + if (gfp->analysis && gfc->pinfo != NULL) { + int j; + for ( ch = 0; ch < gfc->channels_out; ch++ ) { + 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, xr, *masking, l3_enc, scalefac); + } +#endif + + updateStats( gfc ); + + return mp3count; +} diff --git a/lib/lame/encoder.h b/lib/lame/encoder.h new file mode 100644 index 0000000..2fd2c19 --- /dev/null +++ b/lib/lame/encoder.h @@ -0,0 +1,148 @@ +/* + * encoder.h include file + * + * Copyright (c) 2000 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + + +#ifndef LAME_ENCODER_H +#define LAME_ENCODER_H + +/*********************************************************************** +* +* encoder and decoder delays +* +***********************************************************************/ + +/* + * layer III enc->dec delay: 1056 (1057?) (observed) + * layer II enc->dec delay: 480 (481?) (observed) + * + * polyphase 256-16 (dec or enc) = 240 + * mdct 256+32 (9*32) (dec or enc) = 288 + * total: 512+16 + * + * My guess is that delay of polyphase filterbank is actualy 240.5 + * (there are technical reasons for this, see postings in mp3encoder). + * So total Encode+Decode delay = ENCDELAY + 528 + 1 + */ + +/* + * ENCDELAY The encoder delay. + * + * Minimum allowed is MDCTDELAY (see below) + * + * The first 96 samples will be attenuated, so using a value less than 96 + * will result in corrupt data for the first 96-ENCDELAY samples. + * + * suggested: 576 + * set to 1160 to sync with FhG. + */ + +#define ENCDELAY 576 + + + +/* + * make sure there is at least one complete frame after the + * last frame containing real data + * + * Using a value of 288 would be sufficient for a + * a very sophisticated decoder that can decode granule-by-granule instead + * of frame by frame. But lets not assume this, and assume the decoder + * will not decode frame N unless it also has data for frame N+1 + * + */ +/*#define POSTDELAY 288*/ +#define POSTDELAY 1152 + + + +/* + * delay of the MDCT used in mdct.c + * original ISO routines had a delay of 528! + * Takehiro's routines: + */ + +#define MDCTDELAY 48 +#define FFTOFFSET (224+MDCTDELAY) + +/* + * Most decoders, including the one we use, have a delay of 528 samples. + */ + +#define DECDELAY 528 + + +/* number of subbands */ +#define SBLIMIT 32 + +/* parition bands bands */ +#define CBANDS 64 + +/* number of critical bands/scale factor bands where masking is computed*/ +#define SBPSY_l 21 +#define SBPSY_s 12 + +/* total number of scalefactor bands encoded */ +#define SBMAX_l 22 +#define SBMAX_s 13 + + + +/* FFT sizes */ +#define BLKSIZE 1024 +#define HBLKSIZE (BLKSIZE/2 + 1) +#define BLKSIZE_s 256 +#define HBLKSIZE_s (BLKSIZE_s/2 + 1) + + +/* #define switch_pe 1800 */ +#define NORM_TYPE 0 +#define START_TYPE 1 +#define SHORT_TYPE 2 +#define STOP_TYPE 3 + +/* + * Mode Extention: + * When we are in stereo mode, there are 4 possible methods to store these + * two channels. The stereo modes -m? are using a subset of them. + * + * -ms: MPG_MD_LR_LR + * -mj: MPG_MD_LR_LR and MPG_MD_MS_LR + * -mf: MPG_MD_MS_LR + * -mi: all + */ + +#define MPG_MD_LR_LR 0 +#define MPG_MD_LR_I 1 +#define MPG_MD_MS_LR 2 +#define MPG_MD_MS_I 3 + + +#include "machine.h" +#include "lame.h" + +int lame_encode_mp3_frame ( + lame_global_flags* const gfp, + sample_t* inbuf_l, + sample_t* inbuf_r, + unsigned char* mp3buf, + int mp3buf_size ); + +#endif /* LAME_ENCODER_H */ diff --git a/lib/lame/fft.c b/lib/lame/fft.c new file mode 100644 index 0000000..f0d7aca --- /dev/null +++ b/lib/lame/fft.c @@ -0,0 +1,309 @@ +/* +** FFT and FHT routines +** Copyright 1988, 1993; Ron Mayer +** +** fht(fz,n); +** Does a hartley transform of "n" points in the array "fz". +** +** NOTE: This routine uses at least 2 patented algorithms, and may be +** under the restrictions of a bunch of different organizations. +** Although I wrote it completely myself; it is kind of a derivative +** of a routine I once authored and released under the GPL, so it +** may fall under the free software foundation's restrictions; +** it was worked on as a Stanford Univ project, so they claim +** some rights to it; it was further optimized at work here, so +** I think this company claims parts of it. The patents are +** held by R. Bracewell (the FHT algorithm) and O. Buneman (the +** trig generator), both at Stanford Univ. +** If it were up to me, I'd say go do whatever you want with it; +** but it would be polite to give credit to the following people +** if you use this anywhere: +** Euler - probable inventor of the fourier transform. +** Gauss - probable inventor of the FFT. +** Hartley - probable inventor of the hartley transform. +** Buneman - for a really cool trig generator +** Mayer(me) - for authoring this particular version and +** including all the optimizations in one package. +** Thanks, +** Ron Mayer; mayer@acuson.com +** and added some optimization by +** Mather - idea of using lookup table +** Takehiro - some dirty hack for speed up +*/ + +/* $Id: fft.c,v 1.1 2002/04/28 17:30:18 kramm Exp $ */ + +#include "config_static.h" + +#include +#include "util.h" +#include "fft.h" + + + + +#ifdef WITH_DMALLOC +#include +#endif + +#define TRI_SIZE (5-1) /* 1024 = 4**5 */ + +static const FLOAT costab[TRI_SIZE*2] = { + 9.238795325112867e-01, 3.826834323650898e-01, + 9.951847266721969e-01, 9.801714032956060e-02, + 9.996988186962042e-01, 2.454122852291229e-02, + 9.999811752826011e-01, 6.135884649154475e-03 +}; + +static void fht(FLOAT *fz, int n) +{ + const FLOAT *tri = costab; + int k4; + FLOAT *fi, *fn, *gi; + + n <<= 1; /* to get BLKSIZE, because of 3DNow! ASM routine */ + fn = fz + n; + k4 = 4; + do { + FLOAT s1, c1; + int i, k1, k2, k3, kx; + kx = k4 >> 1; + k1 = k4; + k2 = k4 << 1; + k3 = k2 + k1; + k4 = k2 << 1; + fi = fz; + gi = fi + kx; + do { + FLOAT f0,f1,f2,f3; + f1 = fi[0] - fi[k1]; + f0 = fi[0] + fi[k1]; + f3 = fi[k2] - fi[k3]; + f2 = fi[k2] + fi[k3]; + fi[k2] = f0 - f2; + fi[0 ] = f0 + f2; + fi[k3] = f1 - f3; + fi[k1] = f1 + f3; + f1 = gi[0] - gi[k1]; + f0 = gi[0] + gi[k1]; + f3 = SQRT2 * gi[k3]; + f2 = SQRT2 * gi[k2]; + gi[k2] = f0 - f2; + gi[0 ] = f0 + f2; + gi[k3] = f1 - f3; + gi[k1] = f1 + f3; + gi += k4; + fi += k4; + } while (fiwindow_s[0]; + int i; + int j; + int b; + + for (b = 0; b < 3; b++) { + FLOAT *x = &x_real[b][BLKSIZE_s / 2]; + short k = (576 / 3) * (b + 1); + j = BLKSIZE_s / 8 - 1; + do { + FLOAT f0,f1,f2,f3, w; + + i = rv_tbl[j << 2]; + + f0 = ms00(ch01); w = ms10(ch01); f1 = f0 - w; f0 = f0 + w; + f2 = ms20(ch01); w = ms30(ch01); f3 = f2 - w; f2 = f2 + w; + + x -= 4; + x[0] = f0 + f2; + x[2] = f0 - f2; + x[1] = f1 + f3; + x[3] = f1 - f3; + + f0 = ms01(ch01); w = ms11(ch01); f1 = f0 - w; f0 = f0 + w; + f2 = ms21(ch01); w = ms31(ch01); f3 = f2 - w; f2 = f2 + w; + + x[BLKSIZE_s / 2 + 0] = f0 + f2; + x[BLKSIZE_s / 2 + 2] = f0 - f2; + x[BLKSIZE_s / 2 + 1] = f1 + f3; + x[BLKSIZE_s / 2 + 3] = f1 - f3; + } while (--j >= 0); + + gfc->fft_fht(x, BLKSIZE_s/2); + /* BLKSIZE_s/2 because of 3DNow! ASM routine */ + } +} + +void fft_long(lame_internal_flags * const gfc, + FLOAT x[BLKSIZE], int chn, const sample_t *buffer[2] ) +{ + const FLOAT* window = (const FLOAT *)&gfc->window[0]; + int i; + int jj = BLKSIZE / 8 - 1; + x += BLKSIZE / 2; + + do { + FLOAT f0,f1,f2,f3, w; + + i = rv_tbl[jj]; + f0 = ml00(ch01); w = ml10(ch01); f1 = f0 - w; f0 = f0 + w; + f2 = ml20(ch01); w = ml30(ch01); f3 = f2 - w; f2 = f2 + w; + + x -= 4; + x[0] = f0 + f2; + x[2] = f0 - f2; + x[1] = f1 + f3; + x[3] = f1 - f3; + + f0 = ml01(ch01); w = ml11(ch01); f1 = f0 - w; f0 = f0 + w; + f2 = ml21(ch01); w = ml31(ch01); f3 = f2 - w; f2 = f2 + w; + + x[BLKSIZE / 2 + 0] = f0 + f2; + x[BLKSIZE / 2 + 2] = f0 - f2; + x[BLKSIZE / 2 + 1] = f1 + f3; + x[BLKSIZE / 2 + 3] = f1 - f3; + } while (--jj >= 0); + + gfc->fft_fht(x, BLKSIZE/2); + /* BLKSIZE/2 because of 3DNow! ASM routine */ +} + + +void init_fft(lame_internal_flags * const gfc) +{ + FLOAT *window = &gfc->window[0]; + FLOAT *window_s = &gfc->window_s[0]; + int i; + +#if 0 + if (gfc->nsPsy.use) { + for (i = 0; i < BLKSIZE ; i++) + /* blackman window */ + window[i] = 0.42-0.5*cos(2*PI*i/(BLKSIZE-1))+0.08*cos(4*PI*i/(BLKSIZE-1)); + } else { + /* + * calculate HANN window coefficients + */ + for (i = 0; i < BLKSIZE ; i++) + window[i] = 0.5 * (1.0 - cos(2.0 * PI * (i + 0.5) / BLKSIZE)); + } +#endif + + // The type of window used here will make no real difference, but + // in the interest of merging nspsytune stuff - switch to blackman window + for (i = 0; i < BLKSIZE ; i++) + /* blackman window */ + window[i] = 0.42-0.5*cos(2*PI*(i+.5)/BLKSIZE)+ + 0.08*cos(4*PI*(i+.5)/BLKSIZE); + + for (i = 0; i < BLKSIZE_s/2 ; i++) + window_s[i] = 0.5 * (1.0 - cos(2.0 * PI * (i + 0.5) / BLKSIZE_s)); + +#ifdef HAVE_NASM + if (gfc->CPU_features.AMD_3DNow) { + extern void fht_3DN(FLOAT *fz, int n); + gfc->fft_fht = fht_3DN; + } else +#endif +#ifdef USE_FFTSSE + if (gfc->CPU_features.SIMD) { + extern void fht_SSE(FLOAT *fz, int n); + gfc->fft_fht = fht_SSE; + } else +#endif +#ifdef USE_FFTFPU + if (gfc->CPU_features.i387) { + extern void fht_FPU(FLOAT *fz, int n); + gfc->fft_fht = fht_FPU; + } else +#endif + gfc->fft_fht = fht; +} diff --git a/lib/lame/fft.h b/lib/lame/fft.h new file mode 100644 index 0000000..b96c527 --- /dev/null +++ b/lib/lame/fft.h @@ -0,0 +1,37 @@ +/* + * Fast Fourier Transform include file + * + * Copyright (c) 2000 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_FFT_H +#define LAME_FFT_H + +#include "encoder.h" + +void fft_long(lame_internal_flags* const gfc, FLOAT x_real[BLKSIZE], + int chn, const sample_t *data[2] ); + +void fft_short(lame_internal_flags* const gfc, FLOAT x_real[3][BLKSIZE_s], + int chn, const sample_t *data[2] ); + +void init_fft(lame_internal_flags* const gfc ); + +#endif + +/* End of fft.h */ diff --git a/lib/lame/id3tag.c b/lib/lame/id3tag.c new file mode 100644 index 0000000..f3fecd9 --- /dev/null +++ b/lib/lame/id3tag.c @@ -0,0 +1,532 @@ +/* + * id3tag.c -- Write ID3 version 1 and 2 tags. + * + * Copyright (C) 2000 Don Melton. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +/* + * HISTORY: This source file is part of LAME (see http://www.mp3dev.org/mp3/) + * and was originally adapted by Conrad Sanderson + * from mp3info by Ricardo Cerqueira to write only ID3 version 1 + * tags. Don Melton COMPLETELY rewrote it to support version + * 2 tags and be more conformant to other standards while remaining flexible. + * + * NOTE: See http://id3.org/ for more information about ID3 tag formats. + */ + +/* $Id: id3tag.c,v 1.1 2002/04/28 17:30:19 kramm Exp $ */ + +#include "config_static.h" + +#ifdef STDC_HEADERS +# include +# include +# include +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr (), *strrchr (); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#include "lame.h" +#include "id3tag.h" +#include "util.h" +#include "bitstream.h" + +#ifdef WITH_DMALLOC +#include +#endif + +static const char *const genre_names[] = +{ + /* + * NOTE: The spelling of these genre names is identical to those found in + * Winamp and mp3info. + */ + "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", + "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B", + "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska", + "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", + "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental", + "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alt. Rock", + "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", + "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", + "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", + "Cult", "Gangsta Rap", "Top 40", "Christian Rap", "Pop/Funk", "Jungle", + "Native American", "Cabaret", "New Wave", "Psychedelic", "Rave", + "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz", + "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", + "Folk/Rock", "National Folk", "Swing", "Fast-Fusion", "Bebob", "Latin", + "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", + "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", + "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", + "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", + "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", + "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet", + "Punk Rock", "Drum Solo", "A Cappella", "Euro-House", "Dance Hall", + "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie", + "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap", + "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian", + "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop", + "Synthpop" +}; + +#define GENRE_NAME_COUNT \ + ((int)(sizeof genre_names / sizeof (const char *const))) + +static const int genre_alpha_map [] = { + 123, 34, 74, 73, 99, 20, 40, 26, 145, 90, 116, 41, 135, 85, 96, 138, 89, 0, + 107, 132, 65, 88, 104, 102, 97, 136, 61, 141, 32, 1, 112, 128, 57, 140, 2, + 139, 58, 3, 125, 50, 22, 4, 55, 127, 122, 120, 98, 52, 48, 54, 124, 25, 84, + 80, 115, 81, 119, 5, 30, 36, 59, 126, 38, 49, 91, 6, 129, 79, 137, 7, 35, + 100, 131, 19, 33, 46, 47, 8, 29, 146, 63, 86, 71, 45, 142, 9, 77, 82, 64, + 133, 10, 66, 39, 11, 103, 12, 75, 134, 13, 53, 62, 109, 117, 23, 108, 92, + 67, 93, 43, 121, 15, 68, 14, 16, 76, 87, 118, 17, 78, 143, 114, 110, 69, 21, + 111, 95, 105, 42, 37, 24, 56, 44, 101, 83, 94, 106, 147, 113, 18, 51, 130, + 144, 60, 70, 31, 72, 27, 28 +}; + +#define GENRE_ALPHA_COUNT ((int)(sizeof genre_alpha_map / sizeof (int))) + +void +id3tag_genre_list(void (*handler)(int, const char *, void *), void *cookie) +{ + if (handler) { + int i; + for (i = 0; i < GENRE_NAME_COUNT; ++i) { + if (i < GENRE_ALPHA_COUNT) { + int j = genre_alpha_map[i]; + handler(j, genre_names[j], cookie); + } + } + } +} + +#define GENRE_NUM_UNKNOWN 255 + +void +id3tag_init(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + memset(&gfc->tag_spec, 0, sizeof gfc->tag_spec); + gfc->tag_spec.genre = GENRE_NUM_UNKNOWN; +} + + + +void +id3tag_add_v2(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V1_ONLY_FLAG; + gfc->tag_spec.flags |= ADD_V2_FLAG; +} + +void +id3tag_v1_only(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~(ADD_V2_FLAG | V2_ONLY_FLAG); + gfc->tag_spec.flags |= V1_ONLY_FLAG; +} + +void +id3tag_v2_only(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V1_ONLY_FLAG; + gfc->tag_spec.flags |= V2_ONLY_FLAG; +} + +void +id3tag_space_v1(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V2_ONLY_FLAG; + gfc->tag_spec.flags |= SPACE_V1_FLAG; +} + +void +id3tag_pad_v2(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + gfc->tag_spec.flags &= ~V1_ONLY_FLAG; + gfc->tag_spec.flags |= PAD_V2_FLAG; +} + +void +id3tag_set_title(lame_global_flags *gfp, const char *title) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (title && *title) { + gfc->tag_spec.title = title; + gfc->tag_spec.flags |= CHANGED_FLAG; + } +} + +void +id3tag_set_artist(lame_global_flags *gfp, const char *artist) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (artist && *artist) { + gfc->tag_spec.artist = artist; + gfc->tag_spec.flags |= CHANGED_FLAG; + } +} + +void +id3tag_set_album(lame_global_flags *gfp, const char *album) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (album && *album) { + gfc->tag_spec.album = album; + gfc->tag_spec.flags |= CHANGED_FLAG; + } +} + +void +id3tag_set_year(lame_global_flags *gfp, const char *year) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (year && *year) { + int num = atoi(year); + if (num < 0) { + num = 0; + } + /* limit a year to 4 digits so it fits in a version 1 tag */ + if (num > 9999) { + num = 9999; + } + if (num) { + gfc->tag_spec.year = num; + gfc->tag_spec.flags |= CHANGED_FLAG; + } + } +} + +void +id3tag_set_comment(lame_global_flags *gfp, const char *comment) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (comment && *comment) { + gfc->tag_spec.comment = comment; + gfc->tag_spec.flags |= CHANGED_FLAG; + } +} + +void +id3tag_set_track(lame_global_flags *gfp, const char *track) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (track && *track) { + int num = atoi(track); + if (num < 0) { + num = 0; + } + /* limit a track to 255 so it fits in a version 1 tag even though CD + * audio doesn't allow more than 99 tracks */ + if (num > 255) { + num = 255; + } + if (num) { + gfc->tag_spec.track = num; + gfc->tag_spec.flags |= CHANGED_FLAG; + } + } +} + +/* would use real "strcasecmp" but it isn't portable */ +static int +local_strcasecmp(const char *s1, const char *s2) +{ + unsigned char c1; + unsigned char c2; + do { + c1 = tolower(*s1); + c2 = tolower(*s2); + if (!c1) { + break; + } + ++s1; + ++s2; + } while (c1 == c2); + return c1 - c2; +} + +int +id3tag_set_genre(lame_global_flags *gfp, const char *genre) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if (genre && *genre) { + char *str; + int num = strtol(genre, &str, 10); + /* is the input a string or a valid number? */ + if (*str) { + int i; + for (i = 0; i < GENRE_NAME_COUNT; ++i) { + if (!local_strcasecmp(genre, genre_names[i])) { + num = i; + break; + } + } + if (i == GENRE_NAME_COUNT) { + return -1; + } + } else if ((num < 0) || (num >= GENRE_NAME_COUNT)) { + return -1; + } + gfc->tag_spec.genre = num; + gfc->tag_spec.flags |= CHANGED_FLAG; + } + return 0; +} + +static unsigned char * +set_4_byte_value(unsigned char *bytes, unsigned long value) +{ + int index; + for (index = 3; index >= 0; --index) { + bytes[index] = value & 0xfful; + value >>= 8; + } + return bytes + 4; +} + +#define FRAME_ID(a, b, c, d) \ + ( ((unsigned long)(a) << 24) \ + | ((unsigned long)(b) << 16) \ + | ((unsigned long)(c) << 8) \ + | ((unsigned long)(d) << 0) ) +#define TITLE_FRAME_ID FRAME_ID('T', 'I', 'T', '2') +#define ARTIST_FRAME_ID FRAME_ID('T', 'P', 'E', '1') +#define ALBUM_FRAME_ID FRAME_ID('T', 'A', 'L', 'B') +#define YEAR_FRAME_ID FRAME_ID('T', 'Y', 'E', 'R') +#define COMMENT_FRAME_ID FRAME_ID('C', 'O', 'M', 'M') +#define TRACK_FRAME_ID FRAME_ID('T', 'R', 'C', 'K') +#define GENRE_FRAME_ID FRAME_ID('T', 'C', 'O', 'N') + +static unsigned char * +set_frame(unsigned char *frame, unsigned long id, const char *text, + size_t length) +{ + if (length) { + frame = set_4_byte_value(frame, id); + /* Set frame size = total size - header size. Frame header and field + * bytes include 2-byte header flags, 1 encoding descriptor byte, and + * for comment frames: 3-byte language descriptor and 1 content + * descriptor byte */ + frame = set_4_byte_value(frame, ((id == COMMENT_FRAME_ID) ? 5 : 1) + + length); + /* clear 2-byte header flags */ + *frame++ = 0; + *frame++ = 0; + /* clear 1 encoding descriptor byte to indicate ISO-8859-1 format */ + *frame++ = 0; + if (id == COMMENT_FRAME_ID) { + /* use id3lib-compatible bogus language descriptor */ + *frame++ = 'X'; + *frame++ = 'X'; + *frame++ = 'X'; + /* clear 1 byte to make content descriptor empty string */ + *frame++ = 0; + } + while (length--) { + *frame++ = *text++; + } + } + return frame; +} + +int +id3tag_write_v2(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if ((gfc->tag_spec.flags & CHANGED_FLAG) + && !(gfc->tag_spec.flags & V1_ONLY_FLAG)) { + /* calculate length of four fields which may not fit in verion 1 tag */ + size_t title_length = gfc->tag_spec.title + ? strlen(gfc->tag_spec.title) : 0; + size_t artist_length = gfc->tag_spec.artist + ? strlen(gfc->tag_spec.artist) : 0; + size_t album_length = gfc->tag_spec.album + ? strlen(gfc->tag_spec.album) : 0; + size_t comment_length = gfc->tag_spec.comment + ? strlen(gfc->tag_spec.comment) : 0; + /* write tag if explicitly requested or if fields overflow */ + if ((gfc->tag_spec.flags & (ADD_V2_FLAG | V2_ONLY_FLAG)) + || (title_length > 30) + || (artist_length > 30) || (album_length > 30) + || (comment_length > 30) + || (gfc->tag_spec.track && (comment_length > 28))) { + size_t tag_size; + char year[5]; + size_t year_length; + char track[3]; + size_t track_length; + char genre[6]; + size_t genre_length; + unsigned char *tag; + unsigned char *p; + size_t adjusted_tag_size; + unsigned int index; + /* calulate size of tag starting with 10-byte tag header */ + tag_size = 10; + if (title_length) { + /* add 10-byte frame header, 1 encoding descriptor byte ... */ + tag_size += 11 + title_length; + } + if (artist_length) { + tag_size += 11 + artist_length; + } + if (album_length) { + tag_size += 11 + album_length; + } + if (gfc->tag_spec.year) { + year_length = sprintf(year, "%d", gfc->tag_spec.year); + tag_size += 11 + year_length; + } else { + year_length = 0; + } + if (comment_length) { + /* add 10-byte frame header, 1 encoding descriptor byte, + * 3-byte language descriptor, 1 content descriptor byte ... */ + tag_size += 15 + comment_length; + } + if (gfc->tag_spec.track) { + track_length = sprintf(track, "%d", gfc->tag_spec.track); + tag_size += 11 + track_length; + } else { + track_length = 0; + } + if (gfc->tag_spec.genre != GENRE_NUM_UNKNOWN) { + genre_length = sprintf(genre, "(%d)", gfc->tag_spec.genre); + tag_size += 11 + genre_length; + } else { + genre_length = 0; + } + if (gfc->tag_spec.flags & PAD_V2_FLAG) { + /* add 128 bytes of padding */ + tag_size += 128; + } + tag = (unsigned char *)malloc(tag_size); + if (!tag) { + return -1; + } + p = tag; + /* set tag header starting with file identifier */ + *p++ = 'I'; *p++ = 'D'; *p++ = '3'; + /* set version number word */ + *p++ = 3; *p++ = 0; + /* clear flags byte */ + *p++ = 0; + /* calculate and set tag size = total size - header size */ + adjusted_tag_size = tag_size - 10; + /* encode adjusted size into four bytes where most significant + * bit is clear in each byte, for 28-bit total */ + *p++ = (adjusted_tag_size >> 21) & 0x7fu; + *p++ = (adjusted_tag_size >> 14) & 0x7fu; + *p++ = (adjusted_tag_size >> 7) & 0x7fu; + *p++ = adjusted_tag_size & 0x7fu; + + /* + * NOTE: The remainder of the tag (frames and padding, if any) + * are not "unsynchronized" to prevent false MPEG audio headers + * from appearing in the bitstream. Why? Well, most players + * and utilities know how to skip the ID3 version 2 tag by now + * even if they don't read its contents, and it's actually + * very unlikely that such a false "sync" pattern would occur + * in just the simple text frames added here. + */ + + /* set each frame in tag */ + p = set_frame(p, TITLE_FRAME_ID, gfc->tag_spec.title, title_length); + p = set_frame(p, ARTIST_FRAME_ID, gfc->tag_spec.artist, + artist_length); + p = set_frame(p, ALBUM_FRAME_ID, gfc->tag_spec.album, album_length); + p = set_frame(p, YEAR_FRAME_ID, year, year_length); + p = set_frame(p, COMMENT_FRAME_ID, gfc->tag_spec.comment, + comment_length); + p = set_frame(p, TRACK_FRAME_ID, track, track_length); + p = set_frame(p, GENRE_FRAME_ID, genre, genre_length); + /* clear any padding bytes */ + memset(p, 0, tag_size - (p - tag)); + /* write tag directly into bitstream at current position */ + for (index = 0; index < tag_size; ++index) { + add_dummy_byte(gfp, tag[index]); + } + free(tag); + return tag_size; + } + } + return 0; +} + +static unsigned char * +set_text_field(unsigned char *field, const char *text, size_t size, int pad) +{ + while (size--) { + if (text && *text) { + *field++ = *text++; + } else { + *field++ = pad; + } + } + return field; +} + +int +id3tag_write_v1(lame_global_flags *gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + if ((gfc->tag_spec.flags & CHANGED_FLAG) + && !(gfc->tag_spec.flags & V2_ONLY_FLAG)) { + unsigned char tag[128]; + unsigned char *p = tag; + int pad = (gfc->tag_spec.flags & SPACE_V1_FLAG) ? ' ' : 0; + char year[5]; + unsigned int index; + /* set tag identifier */ + *p++ = 'T'; *p++ = 'A'; *p++ = 'G'; + /* set each field in tag */ + p = set_text_field(p, gfc->tag_spec.title, 30, pad); + p = set_text_field(p, gfc->tag_spec.artist, 30, pad); + p = set_text_field(p, gfc->tag_spec.album, 30, pad); + sprintf(year, "%d", gfc->tag_spec.year); + p = set_text_field(p, gfc->tag_spec.year ? year : NULL, 4, pad); + /* limit comment field to 28 bytes if a track is specified */ + p = set_text_field(p, gfc->tag_spec.comment, gfc->tag_spec.track + ? 28 : 30, pad); + if (gfc->tag_spec.track) { + /* clear the next byte to indicate a version 1.1 tag */ + *p++ = 0; + *p++ = gfc->tag_spec.track; + } + *p++ = gfc->tag_spec.genre; + /* write tag directly into bitstream at current position */ + for (index = 0; index < 128; ++index) { + add_dummy_byte(gfp, tag[index]); + } + return 128; + } + return 0; +} diff --git a/lib/lame/id3tag.h b/lib/lame/id3tag.h new file mode 100644 index 0000000..7f63619 --- /dev/null +++ b/lib/lame/id3tag.h @@ -0,0 +1,38 @@ + +#ifndef LAME_ID3_H +#define LAME_ID3_H + +#include "lame.h" + + +#define CHANGED_FLAG (1U << 0) +#define ADD_V2_FLAG (1U << 1) +#define V1_ONLY_FLAG (1U << 2) +#define V2_ONLY_FLAG (1U << 3) +#define SPACE_V1_FLAG (1U << 4) +#define PAD_V2_FLAG (1U << 5) + +struct id3tag_spec +{ + /* private data members */ + int flags; + const char *title; + const char *artist; + const char *album; + int year; + const char *comment; + int track; + int genre; +}; + + +/* write tag into stream at current position */ +extern int id3tag_write_v2(lame_global_flags *gfp); +extern int id3tag_write_v1(lame_global_flags *gfp); +/* + * NOTE: A version 2 tag will NOT be added unless one of the text fields won't + * fit in a version 1 tag (e.g. the title string is longer than 30 characters), + * or the "id3tag_add_v2" or "id3tag_v2_only" functions are used. + */ + +#endif diff --git a/lib/lame/l3side.h b/lib/lame/l3side.h new file mode 100644 index 0000000..d9461b5 --- /dev/null +++ b/lib/lame/l3side.h @@ -0,0 +1,100 @@ +/* + * Layer 3 side include file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_L3SIDE_H +#define LAME_L3SIDE_H + +#include "encoder.h" +#include "machine.h" + +/* Layer III side information. */ + +typedef FLOAT8 D576[576]; +typedef int I576[576]; +typedef FLOAT8 D192_3[192][3]; +typedef int I192_3[192][3]; + + +typedef struct +{ + int l[1+SBMAX_l]; + int s[1+SBMAX_s]; +} scalefac_struct; + + +typedef struct { + FLOAT8 l[SBMAX_l]; + FLOAT8 s[SBMAX_s][3]; +} III_psy_xmin; + +typedef struct { + III_psy_xmin thm; + III_psy_xmin en; +} III_psy_ratio; + +typedef struct { + int part2_3_length; + int big_values; + int count1; + int global_gain; + int scalefac_compress; + int window_switching_flag; + int block_type; + int mixed_block_flag; + int table_select[3]; + int subblock_gain[3]; + int region0_count; + int region1_count; + int preflag; + int scalefac_scale; + int count1table_select; + + int part2_length; + int sfb_lmax; + int sfb_smin; + int count1bits; + /* added for LSF */ + const int *sfb_partition_table; + int slen[4]; +} gr_info; + +typedef struct { + int main_data_begin; + int private_bits; + int resvDrain_pre; + int resvDrain_post; + int scfsi[2][4]; + struct { + struct gr_info_ss { + gr_info tt; + } ch[2]; + } gr[2]; + } III_side_info_t; + +/* Layer III scale factors. */ +/* note: there are only SBPSY_l=(SBMAX_l-1) and SBPSY_s=(SBMAX_s-1) scalefactors. + * Dont know why these would be dimensioned SBMAX_l and SBMAX-s */ +typedef struct { + int l[SBMAX_l]; /* [cb] */ + int s[SBMAX_s][3]; /* [window][cb] */ +} III_scalefac_t; /* [gr][ch] */ + +#endif diff --git a/lib/lame/lame-analysis.h b/lib/lame/lame-analysis.h new file mode 100644 index 0000000..2a1423b --- /dev/null +++ b/lib/lame/lame-analysis.h @@ -0,0 +1,90 @@ +/* + * GTK plotting routines source file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_GTKANAL_H +#define LAME_GTKANAL_H + +#include "encoder.h" + +#define READ_AHEAD 10 /* number of frames to read ahead */ +#define MAXMPGLAG READ_AHEAD /* if the mpg123 lag becomes bigger than this we have to stop */ +#define NUMBACK 6 /* number of frames we can back up */ +#define NUMPINFO (NUMBACK+READ_AHEAD+1) + + + +typedef struct { + int frameNum; /* current frame number */ + int frameNum123; + int num_samples; /* number of pcm samples read for this frame */ + double frametime; /* starting time of frame, in seconds */ + double pcmdata[2][1600]; + double pcmdata2[2][1152+1152-DECDELAY]; + double xr[2][2][576]; + double mpg123xr[2][2][576]; + double ms_ratio[2]; + double ms_ener_ratio[2]; + + /* L,R, M and S values */ + double energy[2][4][BLKSIZE]; + double pe[2][4]; + double thr[2][4][SBMAX_l]; + double en[2][4][SBMAX_l]; + double thr_s[2][4][3*SBMAX_s]; + double en_s[2][4][3*SBMAX_s]; + double ers[2][4]; + + double sfb[2][2][SBMAX_l]; + double sfb_s[2][2][3*SBMAX_s]; + double LAMEsfb[2][2][SBMAX_l]; + double LAMEsfb_s[2][2][3*SBMAX_s]; + + int LAMEqss[2][2]; + int qss[2][2]; + int big_values[2][2]; + int sub_gain[2][2][3]; + + double xfsf[2][2][SBMAX_l]; + double xfsf_s[2][2][3*SBMAX_s]; + + int over[2][2]; + double tot_noise[2][2]; + double max_noise[2][2]; + double over_noise[2][2]; + int blocktype[2][2]; + int scalefac_scale[2][2]; + int preflag[2][2]; + int mpg123blocktype[2][2]; + int mixed[2][2]; + int mainbits[2][2]; + int sfbits[2][2]; + int LAMEmainbits[2][2]; + int LAMEsfbits[2][2]; + int framesize,stereo,js,ms_stereo,i_stereo,emph,bitrate,sampfreq,maindata; + int crc,padding; + int scfsi[2],mean_bits,resvsize; + int totbits; +} plotting_data; + + +extern plotting_data *pinfo; + +#endif diff --git a/lib/lame/lame.c b/lib/lame/lame.c new file mode 100644 index 0000000..df4fdac --- /dev/null +++ b/lib/lame/lame.c @@ -0,0 +1,2239 @@ +/* -*- mode: C; mode: fold -*- */ +/* + * LAME MP3 encoding engine + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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: lame.c,v 1.1 2002/04/28 17:30:20 kramm Exp $ */ + +#include "config_static.h" + + +#include +#include "lame-analysis.h" +#include "lame.h" +#include "util.h" +#include "bitstream.h" +#include "version.h" +#include "tables.h" +#include "quantize_pvt.h" +#include "VbrTag.h" + +#if defined(__FreeBSD__) && !defined(__alpha__) +#include +#endif +#ifdef __riscos__ +#include "asmstuff.h" +#endif + +#ifdef WITH_DMALLOC +#include +#endif + + +static void +lame_init_params_ppflt_lowpass(FLOAT8 amp_lowpass[32], FLOAT lowpass1, + FLOAT lowpass2, int *lowpass_band, + int *minband, int *maxband) +{ + int band; + FLOAT8 freq; + + for (band = 0; band <= 31; band++) { + freq = band / 31.0; + amp_lowpass[band] = 1; + /* this band and above will be zeroed: */ + if (freq >= lowpass2) { + *lowpass_band = Min(*lowpass_band, band); + amp_lowpass[band] = 0; + } + if (lowpass1 < freq && freq < lowpass2) { + *minband = Min(*minband, band); + *maxband = Max(*maxband, band); + amp_lowpass[band] = cos((PI / 2) * + (lowpass1 - freq) / (lowpass2 - lowpass1)); + } + /* + * DEBUGF("lowpass band=%i amp=%f \n", + * band, gfc->amp_lowpass[band]); + */ + } +} + +/* lame_init_params_ppflt */ + +/*}}}*/ +/* static void lame_init_params_ppflt (lame_internal_flags *gfc) *//*{{{ */ + +static void +lame_init_params_ppflt(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + /***************************************************************/ + /* compute info needed for polyphase filter (filter type==0, default) */ + /***************************************************************/ + + int band, maxband, minband; + FLOAT8 freq; + + if (gfc->lowpass1 > 0) { + minband = 999; + maxband = -1; + lame_init_params_ppflt_lowpass(gfc->amp_lowpass, + gfc->lowpass1, gfc->lowpass2, + &gfc->lowpass_band, &minband, &maxband); + /* compute the *actual* transition band implemented by + * the polyphase filter */ + if (minband == 999) { + gfc->lowpass1 = (gfc->lowpass_band - .75) / 31.0; + } + else { + gfc->lowpass1 = (minband - .75) / 31.0; + } + gfc->lowpass2 = gfc->lowpass_band / 31.0; + + gfc->lowpass_start_band = minband; + gfc->lowpass_end_band = maxband; + + /* as the lowpass may have changed above + * calculate the amplification here again + */ + for (band = minband; band <= maxband; band++) { + freq = band / 31.0; + gfc->amp_lowpass[band] = + cos((PI / 2) * (gfc->lowpass1 - freq) / + (gfc->lowpass2 - gfc->lowpass1)); + } + } + else { + gfc->lowpass_start_band = 0; + gfc->lowpass_end_band = -1; /* do not to run into for-loops */ + } + + /* make sure highpass filter is within 90% of what the effective + * highpass frequency will be */ + if (gfc->highpass2 > 0) { + if (gfc->highpass2 < .9 * (.75 / 31.0)) { + gfc->highpass1 = 0; + gfc->highpass2 = 0; + MSGF(gfc, "Warning: highpass filter disabled. " + "highpass frequency too small\n"); + } + } + + if (gfc->highpass2 > 0) { + minband = 999; + maxband = -1; + for (band = 0; band <= 31; band++) { + freq = band / 31.0; + gfc->amp_highpass[band] = 1; + /* this band and below will be zereod */ + if (freq <= gfc->highpass1) { + gfc->highpass_band = Max(gfc->highpass_band, band); + gfc->amp_highpass[band] = 0; + } + if (gfc->highpass1 < freq && freq < gfc->highpass2) { + minband = Min(minband, band); + maxband = Max(maxband, band); + gfc->amp_highpass[band] = + cos((PI / 2) * + (gfc->highpass2 - freq) / + (gfc->highpass2 - gfc->highpass1)); + } + /* + DEBUGF("highpass band=%i amp=%f \n", + band, gfc->amp_highpass[band]); + */ + } + /* compute the *actual* transition band implemented by + * the polyphase filter */ + gfc->highpass1 = gfc->highpass_band / 31.0; + if (maxband == -1) { + gfc->highpass2 = (gfc->highpass_band + .75) / 31.0; + } + else { + gfc->highpass2 = (maxband + .75) / 31.0; + } + + gfc->highpass_start_band = minband; + gfc->highpass_end_band = maxband; + + /* as the highpass may have changed above + * calculate the amplification here again + */ + for (band = minband; band <= maxband; band++) { + freq = band / 31.0; + gfc->amp_highpass[band] = + cos((PI / 2) * (gfc->highpass2 - freq) / + (gfc->highpass2 - gfc->highpass1)); + } + } + else { + gfc->highpass_start_band = 0; + gfc->highpass_end_band = -1; /* do not to run into for-loops */ + } + /* + DEBUGF("lowpass band with amp=0: %i \n",gfc->lowpass_band); + DEBUGF("highpass band with amp=0: %i \n",gfc->highpass_band); + DEBUGF("lowpass band start: %i \n",gfc->lowpass_start_band); + DEBUGF("lowpass band end: %i \n",gfc->lowpass_end_band); + DEBUGF("highpass band start: %i \n",gfc->highpass_start_band); + DEBUGF("highpass band end: %i \n",gfc->highpass_end_band); + */ +} + +/*}}}*/ + + +static void +optimum_bandwidth(double *const lowerlimit, + double *const upperlimit, + const unsigned bitrate, + const int samplefreq, + const double channels) +{ +/* + * Input: + * bitrate total bitrate in bps + * samplefreq output sampling frequency in Hz + * channels 1 for mono, 2+epsilon for MS stereo, 3 for LR stereo + * epsilon is the percentage of LR frames for typical audio + * (I use 'Fade to Gray' by Metallica) + * + * Output: + * lowerlimit: best lowpass frequency limit for input filter in Hz + * upperlimit: best highpass frequency limit for input filter in Hz + */ + double f_low; + double f_high; + double br; + + assert(bitrate >= 8000 && bitrate <= 320000); + assert(samplefreq >= 8000 && samplefreq <= 48000); + assert(channels == 1 || (channels >= 2 && channels <= 3)); + + if (samplefreq >= 32000) + br = + bitrate - (channels == + 1 ? (17 + 4) * 8 : (32 + 4) * 8) * samplefreq / 1152; + else + br = + bitrate - (channels == + 1 ? (9 + 4) * 8 : (17 + 4) * 8) * samplefreq / 576; + + if (channels >= 2.) + br /= 1.75 + 0.25 * (channels - 2.); // MS needs 1.75x mono, LR needs 2.00x mono (experimental data of a lot of albums) + + br *= 0.5; // the sine and cosine term must share the bitrate + +/* + * So, now we have the bitrate for every spectral line. + * Let's look at the current settings: + * + * Bitrate limit bits/line + * 8 kbps 0.34 kHz 4.76 + * 16 kbps 1.9 kHz 2.06 + * 24 kbps 2.8 kHz 2.21 + * 32 kbps 3.85 kHz 2.14 + * 40 kbps 5.1 kHz 2.06 + * 48 kbps 5.6 kHz 2.21 + * 56 kbps 7.0 kHz 2.10 + * 64 kbps 7.7 kHz 2.14 + * 80 kbps 10.1 kHz 2.08 + * 96 kbps 11.2 kHz 2.24 + * 112 kbps 14.0 kHz 2.12 + * 128 kbps 15.4 kHz 2.17 + * 160 kbps 18.2 kHz 2.05 + * 192 kbps 21.1 kHz 2.14 + * 224 kbps 22.0 kHz 2.41 + * 256 kbps 22.0 kHz 2.78 + * + * What can we see? + * Value for 8 kbps is nonsense (although 8 kbps and stereo is nonsense) + * Values are between 2.05 and 2.24 for 16...192 kbps + * Some bitrate lack the following bitrates have: 16, 40, 80, 160 kbps + * A lot of bits per spectral line have: 24, 48, 96 kbps + * + * What I propose? + * A slightly with the bitrate increasing bits/line function. It is + * better to decrease NMR for low bitrates to get a little bit more + * bandwidth. So we have a better trade off between twickling and + * muffled sound. + */ + + f_low = br / log10(br * 4.425e-3); // Tests with 8, 16, 32, 64, 112 and 160 kbps + +/* +GB 04/04/01 +sfb21 is a huge bitrate consumer in vbr with the new ath. +Need to reduce the lowpass to more reasonable values. This extra lowpass +won't reduce quality over 3.87 as the previous ath was doing this lowpass +*/ +/*GB 22/05/01 +I'm also extending this to CBR as tests showed that a +limited bandwidth is increasing quality +*/ + if (f_low>18400) + f_low = 18400+(f_low-18400)/4; + +/* + * What we get now? + * + * Bitrate limit bits/line difference + * 8 kbps (8) 1.89 kHz 0.86 +1.6 kHz + * 16 kbps (8) 3.16 kHz 1.24 +1.2 kHz + * 32 kbps(16) 5.08 kHz 1.54 +1.2 kHz + * 56 kbps(22) 7.88 kHz 1.80 +0.9 kHz + * 64 kbps(22) 8.83 kHz 1.86 +1.1 kHz + * 112 kbps(32) 14.02 kHz 2.12 0.0 kHz + * 112 kbps(44) 13.70 kHz 2.11 -0.3 kHz + * 128 kbps 15.40 kHz 2.17 0.0 kHz + * 160 kbps 16.80 kHz 2.22 -1.4 kHz + * 192 kbps 19.66 kHz 2.30 -1.4 kHz + * 256 kbps 22.05 kHz 2.78 0.0 kHz + */ + + +/* + * Now we try to choose a good high pass filtering frequency. + * This value is currently not used. + * For fu < 16 kHz: sqrt(fu*fl) = 560 Hz + * For fu = 18 kHz: no high pass filtering + * This gives: + * + * 2 kHz => 160 Hz + * 3 kHz => 107 Hz + * 4 kHz => 80 Hz + * 8 kHz => 40 Hz + * 16 kHz => 20 Hz + * 17 kHz => 10 Hz + * 18 kHz => 0 Hz + * + * These are ad hoc values and these can be optimized if a high pass is available. + */ + if (f_low <= 16000) + f_high = 16000. * 20. / f_low; + else if (f_low <= 18000) + f_high = 180. - 0.01 * f_low; + else + f_high = 0.; + + /* + * When we sometimes have a good highpass filter, we can add the highpass + * frequency to the lowpass frequency + */ + + if (lowerlimit != NULL) + *lowerlimit = (f_low>0.5 * samplefreq ? 0.5 * samplefreq : f_low); // roel - fixes mono "-b320 -a" + if (upperlimit != NULL) + *upperlimit = f_high; +/* + * Now the weak points: + * + * - the formula f_low=br/log10(br*4.425e-3) is an ad hoc formula + * (but has a physical background and is easy to tune) + * - the switch to the ATH based bandwidth selecting is the ad hoc + * value of 128 kbps + */ +} + +static int +optimum_samplefreq(int lowpassfreq, int input_samplefreq) +{ +/* + * Rules: + * + * - output sample frequency should NOT be decreased by more than 3% if lowpass allows this + * - if possible, sfb21 should NOT be used + * + * Problem: Switches to 32 kHz at 112 kbps + */ + if (input_samplefreq <= 8000 * 1.03 || lowpassfreq <= 3622) + return 8000; + if (input_samplefreq <= 11025 * 1.03 || lowpassfreq <= 4991) + return 11025; + if (input_samplefreq <= 12000 * 1.03 || lowpassfreq <= 5620) + return 12000; + if (input_samplefreq <= 16000 * 1.03 || lowpassfreq <= 7244) + return 16000; + if (input_samplefreq <= 22050 * 1.03 || lowpassfreq <= 9982) + return 22050; + if (input_samplefreq <= 24000 * 1.03 || lowpassfreq <= 11240) + return 24000; + if (input_samplefreq <= 32000 * 1.03 || lowpassfreq <= 15264) + return 32000; + if (input_samplefreq <= 44100 * 1.03) + return 44100; + return 48000; +} + + +/* set internal feature flags. USER should not access these since + * some combinations will produce strange results */ +void +lame_init_qval(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + + switch (gfp->quality) { + case 9: /* no psymodel, no noise shaping */ + gfc->filter_type = 0; + gfc->psymodel = 0; + gfc->quantization = 0; + gfc->noise_shaping = 0; + gfc->noise_shaping_amp = 0; + gfc->noise_shaping_stop = 0; + gfc->use_best_huffman = 0; + break; + + case 8: + gfp->quality = 7; + case 7: /* use psymodel (for short block and m/s switching), but no noise shapping */ + gfc->filter_type = 0; + gfc->psymodel = 1; + gfc->quantization = 0; + gfc->noise_shaping = 0; + gfc->noise_shaping_amp = 0; + gfc->noise_shaping_stop = 0; + gfc->use_best_huffman = 0; + break; + + case 6: + gfp->quality = 5; + case 5: /* the default */ + gfc->filter_type = 0; + gfc->psymodel = 1; + gfc->quantization = 0; + gfc->noise_shaping = 1; + /**/ gfc->noise_shaping_amp = 0; + gfc->noise_shaping_stop = 0; + gfc->use_best_huffman = 0; + break; + + case 4: + gfp->quality = 3; + case 3: + gfc->filter_type = 0; + gfc->psymodel = 1; + gfc->quantization = 1; + gfc->noise_shaping = 1; + gfc->noise_shaping_amp = 0; + gfc->noise_shaping_stop = 0; + gfc->use_best_huffman = 1; + break; + + case 2: + gfc->filter_type = 0; + gfc->psymodel = 1; + gfc->quantization = 1; + gfc->noise_shaping = 1; + gfc->noise_shaping_amp = 1; + gfc->noise_shaping_stop = 1; + gfc->use_best_huffman = 1; + break; + + case 1: + gfc->filter_type = 0; + gfc->psymodel = 1; + gfc->quantization = 1; + gfc->noise_shaping = 1; + gfc->noise_shaping_amp = 2; + gfc->noise_shaping_stop = 1; + gfc->use_best_huffman = 1; + break; + + case 0: /* 0..1 quality */ + gfc->filter_type = 0; /* 1 not yet coded */ + gfc->psymodel = 1; + gfc->quantization = 1; + gfc->noise_shaping = 1; /* 2=usually lowers quality */ + gfc->noise_shaping_amp = 3; + gfc->noise_shaping_stop = 1; + gfc->use_best_huffman = 1; /* 2 not yet coded */ + } + + /* modifications to the above rules: */ + + /* -Z option toggles scalefactor_scale: */ + if ( (gfp->experimentalZ & 1) > 0) { + gfc->noise_shaping = 2; + } +} + + + + + + + +/* int lame_init_params (lame_global_flags *gfp) *//*{{{ */ + +/******************************************************************** + * initialize internal params based on data in gf + * (globalflags struct filled in by calling program) + * + * OUTLINE: + * + * We first have some complex code to determine bitrate, + * output samplerate and mode. It is complicated by the fact + * that we allow the user to set some or all of these parameters, + * and need to determine best possible values for the rest of them: + * + * 1. set some CPU related flags + * 2. check if we are mono->mono, stereo->mono or stereo->stereo + * 3. compute bitrate and output samplerate: + * user may have set compression ratio + * user may have set a bitrate + * user may have set a output samplerate + * 4. set some options which depend on output samplerate + * 5. compute the actual compression ratio + * 6. set mode based on compression ratio + * + * The remaining code is much simpler - it just sets options + * based on the mode & compression ratio: + * + * set allow_diff_short based on mode + * select lowpass filter based on compression ratio & mode + * set the bitrate index, and min/max bitrates for VBR modes + * disable VBR tag if it is not appropriate + * initialize the bitstream + * initialize scalefac_band data + * set sideinfo_len (based on channels, CRC, out_samplerate) + * write an id3v2 tag into the bitstream + * write VBR tag into the bitstream + * set mpeg1/2 flag + * estimate the number of frames (based on a lot of data) + * + * now we set more flags: + * nspsytune: + * see code + * VBR modes + * see code + * CBR/ABR + * see code + * + * Finally, we set the algorithm flags based on the gfp->quality value + * lame_init_qval(gfp); + * + ********************************************************************/ +int +lame_init_params(lame_global_flags * const gfp) +{ + + int i; + int j; + lame_internal_flags *gfc = gfp->internal_flags; + + gfc->gfp = gfp; + + gfc->Class_ID = 0; + + /* report functions */ + gfc->report.msgf = gfp->report.msgf; + gfc->report.debugf = gfp->report.debugf; + gfc->report.errorf = gfp->report.errorf; + + gfc->CPU_features.i387 = has_i387(); + gfc->CPU_features.AMD_3DNow = has_3DNow(); + gfc->CPU_features.MMX = has_MMX(); + gfc->CPU_features.SIMD = has_SIMD(); + gfc->CPU_features.SIMD2 = has_SIMD2(); + + + if (NULL == gfc->ATH) + gfc->ATH = calloc(1, sizeof(ATH_t)); + + if (NULL == gfc->ATH) + return -2; // maybe error codes should be enumerated in lame.h ?? + + if (NULL == gfc->VBR) + gfc->VBR = calloc(1, sizeof(VBR_t)); + if (NULL == gfc->VBR) + return -2; + + if (NULL == gfc->PSY) + gfc->PSY = calloc(1, sizeof(PSY_t)); + if (NULL == gfc->PSY) + return -2; + +#ifdef KLEMM_44 + /* Select the fastest functions for this CPU */ + init_scalar_functions(gfc); +#endif + + gfc->channels_in = gfp->num_channels; + if (gfc->channels_in == 1) + gfp->mode = MONO; + gfc->channels_out = (gfp->mode == MONO) ? 1 : 2; + gfc->mode_ext = MPG_MD_LR_LR; + if (gfp->mode == MONO) + gfp->force_ms = 0; // don't allow forced mid/side stereo for mono output + + + if (gfp->VBR != vbr_off) { + gfp->free_format = 0; /* VBR can't be mixed with free format */ + } + + if (gfp->VBR == vbr_off && gfp->brate == 0) { + /* no bitrate or compression ratio specified, use a compression ratio of 11.025 */ + if (gfp->compression_ratio == 0) + gfp->compression_ratio = 11.025; /* rate to compress a CD down to exactly 128000 bps */ + } + + + if (gfp->VBR == vbr_off && gfp->brate == 0) { + /* no bitrate or compression ratio specified, use 11.025 */ + if (gfp->compression_ratio == 0) + gfp->compression_ratio = 11.025; /* rate to compress a CD down to exactly 128000 bps */ + } + + /* find bitrate if user specify a compression ratio */ + if (gfp->VBR == vbr_off && gfp->compression_ratio > 0) { + + if (gfp->out_samplerate == 0) + gfp->out_samplerate = map2MP3Frequency( (int)( 0.97 * gfp->in_samplerate ) ); /* round up with a margin of 3% */ + + /* choose a bitrate for the output samplerate which achieves + * specified compression ratio + */ + gfp->brate = + gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 * + gfp-> + compression_ratio); + + /* we need the version for the bitrate table look up */ + gfc->samplerate_index = SmpFrqIndex(gfp->out_samplerate, &gfp->version); + + if (!gfp->free_format) /* for non Free Format find the nearest allowed bitrate */ + gfp->brate = + FindNearestBitrate(gfp->brate, gfp->version, + gfp->out_samplerate); + } + + if (gfp->VBR != vbr_off && gfp->brate >= 320) + gfp->VBR = vbr_off; /* at 160 kbps (MPEG-2/2.5)/ 320 kbps (MPEG-1) only Free format or CBR are possible, no VBR */ + + + if (gfp->out_samplerate == 0) { /* if output sample frequency is not given, find an useful value */ + gfp->out_samplerate = map2MP3Frequency( (int)( 0.97 * gfp->in_samplerate ) ); + + + /* check if user specified bitrate requires downsampling, if compression */ + /* ratio is > 13, choose a new samplerate to get the ratio down to about 10 */ + + if (gfp->VBR == vbr_off && gfp->brate > 0) { + gfp->compression_ratio = + gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 * + gfp->brate); + if (gfp->compression_ratio > 13.) + gfp->out_samplerate = + map2MP3Frequency( (int)( (10. * 1.e3 * gfp->brate) / + (16 * gfc->channels_out))); + } + if (gfp->VBR == vbr_abr) { + gfp->compression_ratio = + gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 * + gfp-> + VBR_mean_bitrate_kbps); + if (gfp->compression_ratio > 13.) + gfp->out_samplerate = + map2MP3Frequency((int)((10. * 1.e3 * gfp->VBR_mean_bitrate_kbps) / + (16 * gfc->channels_out))); + } + } + + if (gfp->ogg) { + gfp->framesize = 1024; + gfp->encoder_delay = ENCDELAY; + gfc->coding = coding_Ogg_Vorbis; + } + else { + gfc->mode_gr = gfp->out_samplerate <= 24000 ? 1 : 2; // Number of granules per frame + gfp->framesize = 576 * gfc->mode_gr; + gfp->encoder_delay = ENCDELAY; + gfc->coding = coding_MPEG_Layer_3; + } + + gfc->frame_size = gfp->framesize; + + gfc->resample_ratio = (double) gfp->in_samplerate / gfp->out_samplerate; + + /* + * sample freq bitrate compression ratio + * [kHz] [kbps/channel] for 16 bit input + * 44.1 56 12.6 + * 44.1 64 11.025 + * 44.1 80 8.82 + * 22.05 24 14.7 + * 22.05 32 11.025 + * 22.05 40 8.82 + * 16 16 16.0 + * 16 24 10.667 + * + */ + /* + * For VBR, take a guess at the compression_ratio. + * For example: + * + * VBR_q compression like + * - 4.4 320 kbps/44 kHz + * 0...1 5.5 256 kbps/44 kHz + * 2 7.3 192 kbps/44 kHz + * 4 8.8 160 kbps/44 kHz + * 6 11 128 kbps/44 kHz + * 9 14.7 96 kbps + * + * for lower bitrates, downsample with --resample + */ + + switch (gfp->VBR) { + case vbr_mt: + case vbr_rh: + case vbr_mtrh: + { + FLOAT8 cmp[] = { 5.7, 6.5, 7.3, 8.2, 9.1, 10, 11, 12, 13, 14 }; + gfp->compression_ratio = cmp[gfp->VBR_q]; + } + break; + case vbr_abr: + gfp->compression_ratio = + gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 * + gfp-> + VBR_mean_bitrate_kbps); + break; + default: + gfp->compression_ratio = + gfp->out_samplerate * 16 * gfc->channels_out / (1.e3 * gfp->brate); + break; + } + + + /* mode = -1 (not set by user) or + * mode = MONO (because of only 1 input channel). + * If mode has been set, then select between STEREO or J-STEREO + * At higher quality (lower compression) use STEREO instead of J-STEREO. + * (unless the user explicitly specified a mode) + * + * The threshold to switch to STEREO is: + * 48 kHz: 171 kbps (used at 192+) + * 44.1 kHz: 160 kbps (used at 160+) + * 32 kHz: 119 kbps (used at 128+) + * + * Note, that for 32 kHz/128 kbps J-STEREO FM recordings sound much + * better than STEREO, so I'm not so very happy with that. + * fs < 32 kHz I have not tested. + */ + if (gfp->mode == NOT_SET) { + if (gfp->compression_ratio < 8) + gfp->mode = STEREO; + else + gfp->mode = JOINT_STEREO; + } + + /* KLEMM's jstereo with ms threshold adjusted via compression ratio */ + if (gfp->mode_automs) { + if (gfp->mode != MONO && gfp->compression_ratio < 6.6) + gfp->mode = STEREO; + } + + + + + + + /****************************************************************/ + /* if a filter has not been enabled, see if we should add one: */ + /****************************************************************/ + if (gfp->lowpassfreq == 0) { + double lowpass; + double highpass; + double channels; + + switch (gfp->mode) { + case MONO: + channels = 1.; + break; + case JOINT_STEREO: + channels = 2. + 0.00; + break; + case DUAL_CHANNEL: + case STEREO: + channels = 3.; + break; + default: + channels = 1.; // just to make data flow analysis happy :-) + assert(0); + break; + } + + optimum_bandwidth(&lowpass, + &highpass, + gfp->out_samplerate * 16 * gfc->channels_out / + gfp->compression_ratio, gfp->out_samplerate, channels); + +/* roel - is this still needed? + if (lowpass > 0.5 * gfp->out_samplerate) { + //MSGF(gfc,"Lowpass @ %7.1f Hz\n", lowpass); + gfc->lowpass1 = gfc->lowpass2 = + lowpass / (0.5 * gfp->out_samplerate); + } +*/ + gfp->lowpassfreq = lowpass; + +#if 0 + if (gfp->out_samplerate != + optimum_samplefreq(lowpass, gfp->in_samplerate)) { + MSGF(gfc, + "I would suggest to use %u Hz instead of %u Hz sample frequency\n", + optimum_samplefreq(lowpass, gfp->in_samplerate), + gfp->out_samplerate); + } + fflush(stderr); +#endif + } + + /* apply user driven high pass filter */ + if (gfp->highpassfreq > 0) { + gfc->highpass1 = 2. * gfp->highpassfreq / gfp->out_samplerate; /* will always be >=0 */ + if (gfp->highpasswidth >= 0) + gfc->highpass2 = + 2. * (gfp->highpassfreq + + gfp->highpasswidth) / gfp->out_samplerate; + else /* 0% above on default */ + gfc->highpass2 = + (1 + 0.00) * 2. * gfp->highpassfreq / gfp->out_samplerate; + } + + /* apply user driven low pass filter */ + if (gfp->lowpassfreq > 0) { + gfc->lowpass2 = 2. * gfp->lowpassfreq / gfp->out_samplerate; /* will always be >=0 */ + if (gfp->lowpasswidth >= 0) { + gfc->lowpass1 = + 2. * (gfp->lowpassfreq - + gfp->lowpasswidth) / gfp->out_samplerate; + if (gfc->lowpass1 < 0) /* has to be >= 0 */ + gfc->lowpass1 = 0; + } + else { /* 0% below on default */ + gfc->lowpass1 = + (1 - 0.00) * 2. * gfp->lowpassfreq / gfp->out_samplerate; + } + } + + + + + /**********************************************************************/ + /* compute info needed for polyphase filter (filter type==0, default) */ + /**********************************************************************/ + lame_init_params_ppflt(gfp); + + + /*******************************************************/ + /* compute info needed for FIR filter (filter_type==1) */ + /*******************************************************/ + /* not yet coded */ + + + + /******************************************************* + * samplerate and bitrate index + *******************************************************/ + gfc->samplerate_index = SmpFrqIndex(gfp->out_samplerate, &gfp->version); + if (gfc->samplerate_index < 0) + return -1; + + if (gfp->VBR == vbr_off) { + if (gfp->free_format) { + gfc->bitrate_index = 0; + } + else { + gfc->bitrate_index = BitrateIndex(gfp->brate, gfp->version, + gfp->out_samplerate); + if (gfc->bitrate_index < 0) + return -1; + } + } + else { /* choose a min/max bitrate for VBR */ + /* if the user didn't specify VBR_max_bitrate: */ + gfc->VBR_min_bitrate = 1; /* default: allow 8 kbps (MPEG-2) or 32 kbps (MPEG-1) */ + gfc->VBR_max_bitrate = 14; /* default: allow 160 kbps (MPEG-2) or 320 kbps (MPEG-1) */ + + if (gfp->VBR_min_bitrate_kbps) + if ( + (gfc->VBR_min_bitrate = + BitrateIndex(gfp->VBR_min_bitrate_kbps, gfp->version, + gfp->out_samplerate)) < 0) return -1; + if (gfp->VBR_max_bitrate_kbps) + if ( + (gfc->VBR_max_bitrate = + BitrateIndex(gfp->VBR_max_bitrate_kbps, gfp->version, + gfp->out_samplerate)) < 0) return -1; + + gfp->VBR_min_bitrate_kbps = + bitrate_table[gfp->version][gfc->VBR_min_bitrate]; + gfp->VBR_max_bitrate_kbps = + bitrate_table[gfp->version][gfc->VBR_max_bitrate]; + + gfp->VBR_mean_bitrate_kbps = + Min(bitrate_table[gfp->version][gfc->VBR_max_bitrate], + gfp->VBR_mean_bitrate_kbps); + gfp->VBR_mean_bitrate_kbps = + Max(bitrate_table[gfp->version][gfc->VBR_min_bitrate], + gfp->VBR_mean_bitrate_kbps); + + + } + + /* for CBR, we will write an "info" tag. */ + // if ((gfp->VBR == vbr_off)) + // gfp->bWriteVbrTag = 0; + + if (gfp->ogg) + gfp->bWriteVbrTag = 0; +#if defined(HAVE_GTK) + if (gfp->analysis) + gfp->bWriteVbrTag = 0; +#endif + + /* some file options not allowed if output is: not specified or stdout */ + if (gfc->pinfo != NULL) + gfp->bWriteVbrTag = 0; /* disable Xing VBR tag */ + + init_bit_stream_w(gfc); + + j = + gfc->samplerate_index + (3 * gfp->version) + 6 * (gfp->out_samplerate < + 16000); + for (i = 0; i < SBMAX_l + 1; i++) + gfc->scalefac_band.l[i] = sfBandIndex[j].l[i]; + for (i = 0; i < SBMAX_s + 1; i++) + gfc->scalefac_band.s[i] = sfBandIndex[j].s[i]; + + /* determine the mean bitrate for main data */ + if (gfp->version == 1) /* MPEG 1 */ + gfc->sideinfo_len = (gfc->channels_out == 1) ? 4 + 17 : 4 + 32; + else /* MPEG 2 */ + gfc->sideinfo_len = (gfc->channels_out == 1) ? 4 + 9 : 4 + 17; + + if (gfp->error_protection) + gfc->sideinfo_len += 2; + + lame_init_bitstream(gfp); + + + if (gfp->version == 1) /* 0 indicates use lower sample freqs algorithm */ + gfc->is_mpeg1 = 1; /* yes */ + else + gfc->is_mpeg1 = 0; /* no */ + + gfc->Class_ID = LAME_ID; + + + if (gfp->exp_nspsytune & 1) { + int i,j; + + gfc->nsPsy.use = 1; + gfc->nsPsy.safejoint = (gfp->exp_nspsytune & 2) != 0; + for (i = 0; i < 19; i++) + gfc->nsPsy.pefirbuf[i] = 700; + + if (gfp->ATHtype == -1) + gfp->ATHtype = 4; + + gfc->nsPsy.bass = gfc->nsPsy.alto = gfc->nsPsy.treble = 0; + + i = (gfp->exp_nspsytune >> 2) & 63; + if (i >= 32) + i -= 64; + gfc->nsPsy.bass = pow(10, i / 4.0 / 10.0); + i = (gfp->exp_nspsytune >> 8) & 63; + if (i >= 32) + i -= 64; + gfc->nsPsy.alto = pow(10, i / 4.0 / 10.0); + i = (gfp->exp_nspsytune >> 14) & 63; + if (i >= 32) + i -= 64; + gfc->nsPsy.treble = pow(10, i / 4.0 / 10.0); + /* to be compatible with Naoki's original code, the next 6 bits + * define only the amount of changing treble for sfb21 */ + j = (gfp->exp_nspsytune >> 20) & 63; + if (j >= 32) + j -= 64; + gfc->nsPsy.sfb21 = pow(10, (i+j) / 4.0 / 10.0); + } + + assert( gfp->VBR_q <= 9 ); + assert( gfp->VBR_q >= 0 ); + + gfc->PSY->tonalityPatch = 0; + + switch (gfp->VBR) { + + case vbr_mt: + gfp->VBR = vbr_mtrh; + + case vbr_mtrh: + + if (gfp->ATHtype < 0) gfp->ATHtype = 4; + if (gfp->quality < 0) gfp->quality = 2; + if (gfp->quality > 7) { + gfp->quality = 7; // needs psymodel + ERRORF( gfc, "VBR needs a psymodel, switching to quality level 7\n"); + } + + /* tonality + */ + if (gfp->cwlimit <= 0) gfp->cwlimit = 0.42 * gfp->out_samplerate; + gfc->PSY->tonalityPatch = 1; + + if ( gfp->experimentalX <= 4 && gfp->experimentalX >= 0 ) + { /* map experimentalX settings to internal secltions */ + static char const map[] = {2,1,0,3,6}; + gfc->VBR->quality = map[gfp->experimentalX]; + } + else /* defaulting to */ + { + gfc->VBR->quality = 2; + } + if ( gfc->VBR->quality > 5 ) { + static float const dbQ[10] = { -6,-4.75,-3.5,-2.25,-1,.25,1.5,2.75,4,5.25 }; + gfc->VBR->mask_adjust = dbQ[gfp->VBR_q]; + gfc->VBR->smooth = 1; // not finally + } + else { + static const float dbQ[10]={-2.,-1.0,-.66,-.33,0.,0.33,.66,1.0,1.33,1.66}; + gfc->VBR->mask_adjust = dbQ[gfp->VBR_q]; + gfc->VBR->smooth = 1; + } + if ( gfc->VBR->quality == 1 ) { + static float const dbQ[10] = { -2., -1.4, -.7, 0, .7, 1.5, 2.3, 3.1, 4., 5 }; + gfc->VBR->mask_adjust = dbQ[gfp->VBR_q]; + gfc->VBR->smooth = 0; + } + if ( gfc->VBR->quality == 0 ) { + static float const dbQ[10] = { -1., -.6, -.3, 0, 1, 2, 3, 4, 5, 6}; + gfc->VBR->mask_adjust = dbQ[gfp->VBR_q]; + gfc->VBR->smooth = 0; + gfc->PSY->tonalityPatch = 0; + } + + gfc->VBR->bitpressure = 1; + + if (gfp->experimentalY) + gfc->sfb21_extra = 0; + else + gfc->sfb21_extra = (gfp->out_samplerate > 44000); + + if ( gfp->athaa_type < 0 ) + gfc->ATH->use_adjust = 3; + else + gfc->ATH->use_adjust = gfp->athaa_type; + + break; + + + case vbr_rh: + + if (gfp->VBR == vbr_rh) /* because of above fall thru */ + { static const FLOAT8 dbQ[10]={-2.,-1.0,-.66,-.33,0.,0.33,.66,1.0,1.33,1.66}; + static const FLOAT8 dbQns[10]={- 4,- 3,-2,-1,0,0.7,1.4,2.1,2.8,3.5}; + /*static const FLOAT8 atQns[10]={-16,-12,-8,-4,0, 1, 2, 3, 4, 5};*/ + if ( gfc->nsPsy.use ) + gfc->VBR->mask_adjust = dbQns[gfp->VBR_q]; + else { + gfc->PSY->tonalityPatch = 1; + gfc->VBR->mask_adjust = dbQ[gfp->VBR_q]; + } + } + gfc->VBR->bitpressure = 1; + + /* use Gabriel's adaptative ATH shape for VBR by default + */ + if (gfp->ATHtype == -1) + gfp->ATHtype = 4; + + /* automatic ATH adjustment on, VBR modes need it + */ + if ( gfp->athaa_type < 0 ) + gfc->ATH->use_adjust = 3; + else + gfc->ATH->use_adjust = gfp->athaa_type; + + /* sfb21 extra only with MPEG-1 at higher sampling rates + */ + if ( gfp->experimentalY ) + gfc->sfb21_extra = 0; + else + gfc->sfb21_extra = (gfp->out_samplerate > 44000); + + /* VBR needs at least the output of GPSYCHO, + * so we have to garantee that by setting a minimum + * quality level, actually level 5 does it. + * the -v and -V x settings switch the quality to level 2 + * you would have to add a -q 5 to reduce the quality + * down to level 5 + */ + if (gfp->quality > 5) + gfp->quality = 5; + + + /* default quality setting is 2 + */ + if (gfp->quality < 0) + gfp->quality = 2; + + break; + + default: + + if (gfp->ATHtype == -1) + gfp->ATHtype = 2; + + /* automatic ATH adjustment off by default + * not so important for CBR code? + */ + if ( gfp->athaa_type < 0 ) + gfc->ATH->use_adjust = 0; + else + gfc->ATH->use_adjust = gfp->athaa_type; + + + /* no sfb21 extra with CBR code + */ + gfc->sfb21_extra = 0; + + /* default quality setting for CBR/ABR is 5 + */ + if (gfp->quality < 0) + gfp->quality = 5; + + break; + } + /* just another daily changing developer switch */ + if ( gfp->tune ) gfc->VBR->mask_adjust = gfp->tune_value_a; + + /* initialize internal qval settings */ + lame_init_qval(gfp); + +#ifdef KLEMM_44 + gfc->mfbuf[0] = (sample_t *) calloc(sizeof(sample_t), MFSIZE); + gfc->mfbuf[1] = (sample_t *) calloc(sizeof(sample_t), MFSIZE); + gfc->sampfreq_in = unround_samplefrequency(gfp->in_samplerate); + gfc->sampfreq_out = gfp->out_samplerate; + gfc->resample_in = resample_open(gfc->sampfreq_in, + gfc->sampfreq_out, -1.0 /* Auto */, 32); +#endif + + /* initialize internal adaptive ATH settings -jd */ + gfc->athaa_sensitivity_p = pow( 10.0, gfp->athaa_sensitivity / -10.0 ); + + + gfc->PSY->cwlimit = gfp->cwlimit <= 0 ? 8871.7f : gfp->cwlimit; + + if (gfp->short_blocks == short_block_not_set) { + gfp->short_blocks = short_block_allowed; + } + if (gfp->short_blocks == short_block_allowed && gfp->mode == JOINT_STEREO) { + gfp->short_blocks = short_block_coupled; + } + + if ( gfp->athaa_loudapprox < 0 ) gfp->athaa_loudapprox = 2; + + if (gfp->useTemporal < 0 ) gfp->useTemporal = 1; // on by default + + + if ( gfp->experimentalY ) + MSGF(gfc,"\n *** WARNING *** the meaning of the experimental -Y has changed!\n" + " now it tells LAME to ignore sfb21 noise shaping (VBR)\n\n"); + + if ( gfp->preset_expopts && gfc->presetTune.use < 1 ) + MSGF(gfc,"\n*** WARNING ***\n\n" + "Specialized tunings for the preset you are using have been deactivated.\n" + "This is *NOT* recommended and will lead to a decrease in quality!\n" + "\n*** WARNING ***\n\n"); + + return 0; +} + +/*}}}*/ +/* void lame_print_config (lame_global_flags *gfp) *//*{{{ */ + +/* + * print_config + * + * Prints some selected information about the coding parameters via + * the macro command MSGF(), which is currently mapped to lame_errorf + * (reports via a error function?), which is a printf-like function + * for . + */ + +void +lame_print_config(const lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + double out_samplerate = gfp->out_samplerate; + double in_samplerate = gfp->out_samplerate * gfc->resample_ratio; + + MSGF(gfc, "LAME version %s (%s)\n", get_lame_version(), get_lame_url()); + + if (gfc->CPU_features.MMX + || gfc->CPU_features.AMD_3DNow + || gfc->CPU_features.SIMD || gfc->CPU_features.SIMD2) { + MSGF(gfc, "CPU features:"); + + if (gfc->CPU_features.i387) + MSGF(gfc, " i387"); + if (gfc->CPU_features.MMX) +#ifdef MMX_choose_table + MSGF(gfc, ", MMX (ASM used)"); +#else + MSGF(gfc, ", MMX"); +#endif + if (gfc->CPU_features.AMD_3DNow) + MSGF(gfc, ", 3DNow!"); + if (gfc->CPU_features.SIMD) + MSGF(gfc, ", SIMD"); + if (gfc->CPU_features.SIMD2) + MSGF(gfc, ", SIMD2"); + MSGF(gfc, "\n"); + } + + if (gfp->num_channels == 2 && gfc->channels_out == 1 /* mono */ ) { + MSGF + (gfc, + "Autoconverting from stereo to mono. Setting encoding to mono mode.\n"); + } + + if (gfc->resample_ratio != 1.) { + MSGF(gfc, "Resampling: input %g kHz output %g kHz\n", + 1.e-3 * in_samplerate, 1.e-3 * out_samplerate); + } + + if (gfc->filter_type == 0) { + if (gfc->highpass2 > 0.) + MSGF + (gfc, + "Using polyphase highpass filter, transition band: %5.0f Hz - %5.0f Hz\n", + 0.5 * gfc->highpass1 * out_samplerate, + 0.5 * gfc->highpass2 * out_samplerate); + if (gfc->lowpass1 > 0.) { + MSGF + (gfc, + "Using polyphase lowpass filter, transition band: %5.0f Hz - %5.0f Hz\n", + 0.5 * gfc->lowpass1 * out_samplerate, + 0.5 * gfc->lowpass2 * out_samplerate); + } + else { + MSGF(gfc, "polyphase lowpass filter disabled\n"); + } + } + else { + MSGF(gfc, "polyphase filters disabled\n"); + } + + if (gfp->free_format) { + MSGF(gfc, + "Warning: many decoders cannot handle free format bitstreams\n"); + if (gfp->brate > 320) { + MSGF + (gfc, + "Warning: many decoders cannot handle free format bitrates >320 kbps (see documentation)\n"); + } + } +} + + +/** rh: + * some pretty printing is very welcome at this point! + * so, if someone is willing to do so, please do it! + * add more, if you see more... + */ +void +lame_print_internals( const lame_global_flags * gfp ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + const char * pc = ""; + + /* compiler/processor optimizations, operational, etc. + */ + MSGF( gfc, "\nmisc:\n\n" ); + + MSGF( gfc, "\tscaling: %f\n", gfp->scale ); + MSGF( gfc, "\tch0 (left) scaling: %f\n", gfp->scale_left ); + MSGF( gfc, "\tch1 (right) scaling: %f\n", gfp->scale_right ); + MSGF( gfc, "\tfilter type: %d\n", gfc->filter_type ); + pc = gfc->quantization ? "xr^3/4" : "ISO"; + MSGF( gfc, "\tquantization: %s\n", pc ); + switch( gfc->use_best_huffman ) { + default: pc = "normal"; break; + case 1: pc = "best (outside loop)"; break; + case 2: pc = "best (inside loop, slow)"; break; + } + MSGF( gfc, "\thuffman search: %s\n", pc ); + MSGF( gfc, "\texperimental X=%d Y=%d Z=%d\n", gfp->experimentalX, gfp->experimentalY, gfp->experimentalZ ); + MSGF( gfc, "\t...\n" ); + + /* everything controlling the stream format + */ + MSGF( gfc, "\nstream format:\n\n" ); + switch ( gfp->version ) { + case 0: pc = "2.5"; break; + case 1: pc = "1"; break; + case 2: pc = "2"; break; + default: pc = "?"; break; + } + MSGF( gfc, "\tMPEG-%s Layer 3\n", pc ); + switch ( gfp->mode ) { + case JOINT_STEREO: pc = "joint stereo"; break; + case STEREO : pc = "stereo"; break; + case DUAL_CHANNEL: pc = "dual channel"; break; + case MONO : pc = "mono"; break; + case NOT_SET : pc = "not set (error)"; break; + default : pc = "unknown (error)"; break; + } + MSGF( gfc, "\t%d channel - %s\n", gfc->channels_out, pc ); + switch ( gfp->padding_type ) { + case PAD_NO : pc = "off"; break; + case PAD_ALL : pc = "all"; break; + case PAD_ADJUST: pc = "auto"; break; + default : pc = "(error)"; break; + } + MSGF( gfc, "\tpadding: %s\n", pc ); + + if ( vbr_default == gfp->VBR ) pc = "(default)"; + else if ( gfp->free_format ) pc = "(free format)"; + else pc = ""; + switch ( gfp->VBR ) { + case vbr_off : MSGF( gfc, "\tconstant bitrate - CBR %s\n", pc ); break; + case vbr_abr : MSGF( gfc, "\tvariable bitrate - ABR %s\n", pc ); break; + case vbr_rh : MSGF( gfc, "\tvariable bitrate - VBR rh %s\n", pc ); break; + case vbr_mt : MSGF( gfc, "\tvariable bitrate - VBR mt %s\n", pc ); break; + case vbr_mtrh: MSGF( gfc, "\tvariable bitrate - VBR mtrh %s\n", pc ); break; + default : MSGF( gfc, "\t ?? oops, some new one ?? \n" ); break; + } + if (gfp->bWriteVbrTag) + MSGF( gfc, "\tusing LAME Tag\n" ); + MSGF( gfc, "\t...\n" ); + + /* everything controlling psychoacoustic settings, like ATH, etc. + */ + MSGF( gfc, "\npsychoacoustic:\n\n" ); + + MSGF( gfc, "\ttonality estimation limit: %f Hz\n", gfc->PSY->cwlimit ); + switch ( gfp->short_blocks ) { + default: + case short_block_not_set: pc = "?"; break; + case short_block_allowed: pc = "allowed"; break; + case short_block_coupled: pc = "channel coupled"; break; + case short_block_dispensed: pc = "dispensed"; break; + case short_block_forced: pc = "forced"; break; + } + MSGF( gfc, "\tusing short blocks: %s\n", pc ); + MSGF( gfc, "\tadjust masking: %f dB\n", gfc->VBR->mask_adjust ); + MSGF( gfc, "\tpsymodel: %d\n", gfc->psymodel ); + MSGF( gfc, "\tnoise shaping: %d\n", gfc->noise_shaping ); + MSGF( gfc, "\t ^ amplification: %d\n", gfc->noise_shaping_amp ); + MSGF( gfc, "\t ^ stopping: %d\n", gfc->noise_shaping_stop ); + + pc = "using"; + if ( gfp->ATHshort ) pc = "the only masking for short blocks"; + if ( gfp->ATHonly ) pc = "the only masking"; + if ( gfp->noATH ) pc = "not used"; + MSGF( gfc, "\tATH: %s\n", pc ); + MSGF( gfc, "\t ^ type: %d\n", gfp->ATHtype ); + MSGF( gfc, "\t ^ adjust type: %d\n", gfc->ATH->use_adjust ); + MSGF( gfc, "\t ^ adapt threshold type: %d\n", gfp->athaa_loudapprox ); + + if ( gfc->nsPsy.use ) { + MSGF( gfc, "\texperimental psy tunings by Naoki Shibata\n" ); + MSGF( gfc, "\t adjust masking bass=%g dB, alto=%g dB, treble=%g dB, sfb21=%g dB\n", + 10*log10(gfc->nsPsy.bass), 10*log10(gfc->nsPsy.alto), + 10*log10(gfc->nsPsy.treble), 10*log10(gfc->nsPsy.sfb21) ); + } + pc = gfp->useTemporal ? "yes" : "no"; + MSGF( gfc, "\tusing temporal masking effect: %s\n", pc ); + MSGF( gfc, "\t...\n" ); + + /* that's all ? + */ + MSGF( gfc, "\n" ); + return; +} + + + +/* int lame_encode_frame (lame_global_flags *gfp, sample_t inbuf_l[],sample_t inbuf_r[], char *mp3buf, int mp3buf_size) *//*{{{ */ + +/* routine to feed exactly one frame (gfp->framesize) worth of data to the +encoding engine. All buffering, resampling, etc, handled by calling +program. +*/ +int +lame_encode_frame(lame_global_flags * gfp, + sample_t inbuf_l[], sample_t inbuf_r[], + unsigned char *mp3buf, int mp3buf_size) +{ + int ret; + if (gfp->ogg) { +#ifdef HAVE_VORBIS_ENCODER + ret = lame_encode_ogg_frame(gfp, inbuf_l, inbuf_r, mp3buf, mp3buf_size); +#else + return -5; /* wanna encode ogg without vorbis */ +#endif + } + else { + ret = lame_encode_mp3_frame(gfp, inbuf_l, inbuf_r, mp3buf, mp3buf_size); + } + + + + gfp->frameNum++; + return ret; +} + +/*}}}*/ +/* int lame_encode_buffer (lame_global_flags* gfp, short int buffer_l[], short int buffer_r[], int nsamples, char* mp3buf, int mp3buf_size )*//*{{{ */ + + + +/* + * THE MAIN LAME ENCODING INTERFACE + * mt 3/00 + * + * input pcm data, output (maybe) mp3 frames. + * This routine handles all buffering, resampling and filtering for you. + * The required mp3buffer_size can be computed from num_samples, + * samplerate and encoding rate, but here is a worst case estimate: + * + * mp3buffer_size in bytes = 1.25*num_samples + 7200 + * + * return code = number of bytes output in mp3buffer. can be 0 +*/ +int +lame_encode_buffer_sample_t(lame_global_flags * gfp, + sample_t buffer_l[], + sample_t buffer_r[], + int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int mp3size = 0, ret, i, ch, mf_needed; + int mp3out; + sample_t *mfbuf[2]; + sample_t *in_buffer[2]; + + if (gfc->Class_ID != LAME_ID) + return -3; + + if (nsamples == 0) + return 0; + + /* copy out any tags that may have been written into bitstream */ + mp3out = copy_buffer(gfc,mp3buf,mp3buf_size,0); + if (mp3out<0) return mp3out; // not enough buffer space + mp3buf += mp3out; + mp3size += mp3out; + + + in_buffer[0]=buffer_l; + in_buffer[1]=buffer_r; + + + /* some sanity checks */ +#if ENCDELAY < MDCTDELAY +# error ENCDELAY is less than MDCTDELAY, see encoder.h +#endif +#if FFTOFFSET > BLKSIZE +# error FFTOFFSET is greater than BLKSIZE, see encoder.h +#endif + + mf_needed = BLKSIZE + gfp->framesize - FFTOFFSET; /* amount needed for FFT */ + mf_needed = Max(mf_needed, 286 + 576 * (1 + gfc->mode_gr)); /* amount needed for MDCT/filterbank */ + assert(MFSIZE >= mf_needed); + + mfbuf[0] = gfc->mfbuf[0]; + mfbuf[1] = gfc->mfbuf[1]; + + if (gfp->num_channels == 2 && gfc->channels_out == 1) { + /* downsample to mono */ + for (i = 0; i < nsamples; ++i) { + in_buffer[0][i] = + 0.5 * ((FLOAT8) in_buffer[0][i] + in_buffer[1][i]); + in_buffer[1][i] = 0.0; + } + } + + + while (nsamples > 0) { + int n_in = 0; /* number of input samples processed with fill_buffer */ + int n_out = 0; /* number of samples output with fill_buffer */ + /* n_in <> n_out if we are resampling */ + + /* copy in new samples into mfbuf, with resampling & scaling if necessary */ + fill_buffer(gfp, mfbuf, in_buffer, nsamples, &n_in, &n_out); + + /* update in_buffer counters */ + nsamples -= n_in; + in_buffer[0] += n_in; + if (gfc->channels_out == 2) + in_buffer[1] += n_in; + + /* update mfbuf[] counters */ + gfc->mf_size += n_out; + assert(gfc->mf_size <= MFSIZE); + gfc->mf_samples_to_encode += n_out; + + + if (gfc->mf_size >= mf_needed) { + /* encode the frame. */ + // mp3buf = pointer to current location in buffer + // mp3buf_size = size of original mp3 output buffer + // = 0 if we should not worry about the + // buffer size because calling program is + // to lazy to compute it + // mp3size = size of data written to buffer so far + // mp3buf_size-mp3size = amount of space avalable + + int buf_size=mp3buf_size - mp3size; + if (mp3buf_size==0) buf_size=0; + + ret = + lame_encode_frame(gfp, mfbuf[0], mfbuf[1], mp3buf,buf_size); + + if (ret < 0) goto retr; + mp3buf += ret; + mp3size += ret; + + /* shift out old samples */ + gfc->mf_size -= gfp->framesize; + gfc->mf_samples_to_encode -= gfp->framesize; + for (ch = 0; ch < gfc->channels_out; ch++) + for (i = 0; i < gfc->mf_size; i++) + mfbuf[ch][i] = mfbuf[ch][i + gfp->framesize]; + } + } + assert(nsamples == 0); + ret = mp3size; + + retr: + return ret; +} + + +int +lame_encode_buffer(lame_global_flags * gfp, + const short int buffer_l[], + const short int buffer_r[], + const int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int ret, i; + sample_t *in_buffer[2]; + + if (gfc->Class_ID != LAME_ID) + return -7; //-3 + + if (nsamples == 0) + return 0; + + in_buffer[0] = calloc(sizeof(sample_t), nsamples); + in_buffer[1] = calloc(sizeof(sample_t), nsamples); + + if (in_buffer[0] == NULL || in_buffer[1] == NULL) { + ERRORF(gfc, "Error: can't allocate in_buffer buffer\n"); + return -2; + } + + /* make a copy of input buffer, changing type to sample_t */ + for (i = 0; i < nsamples; i++) { + in_buffer[0][i] = buffer_l[i]; + in_buffer[1][i] = buffer_r[i]; + } + + ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1], + nsamples, mp3buf, mp3buf_size); + + free(in_buffer[0]); + free(in_buffer[1]); + return ret; +} + + +int +lame_encode_buffer_float(lame_global_flags * gfp, + const float buffer_l[], + const float buffer_r[], + const int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int ret, i; + sample_t *in_buffer[2]; + + if (gfc->Class_ID != LAME_ID) + return -3; + + if (nsamples == 0) + return 0; + + in_buffer[0] = calloc(sizeof(sample_t), nsamples); + in_buffer[1] = calloc(sizeof(sample_t), nsamples); + + if (in_buffer[0] == NULL || in_buffer[1] == NULL) { + ERRORF(gfc, "Error: can't allocate in_buffer buffer\n"); + return -2; + } + + /* make a copy of input buffer, changing type to sample_t */ + for (i = 0; i < nsamples; i++) { + in_buffer[0][i] = buffer_l[i]; + in_buffer[1][i] = buffer_r[i]; + } + + ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1], + nsamples, mp3buf, mp3buf_size); + + free(in_buffer[0]); + free(in_buffer[1]); + return ret; +} + + + +int +lame_encode_buffer_int(lame_global_flags * gfp, + const int buffer_l[], + const int buffer_r[], + const int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int ret, i; + sample_t *in_buffer[2]; + + if (gfc->Class_ID != LAME_ID) + return -3; + + if (nsamples == 0) + return 0; + + in_buffer[0] = calloc(sizeof(sample_t), nsamples); + in_buffer[1] = calloc(sizeof(sample_t), nsamples); + + if (in_buffer[0] == NULL || in_buffer[1] == NULL) { + ERRORF(gfc, "Error: can't allocate in_buffer buffer\n"); + return -2; + } + + /* make a copy of input buffer, changing type to sample_t */ + for (i = 0; i < nsamples; i++) { + /* internal code expects +/- 32768.0 */ + in_buffer[0][i] = buffer_l[i] * (1.0 / ( 1 << (8 * sizeof(int) - 16))); + in_buffer[1][i] = buffer_r[i] * (1.0 / ( 1 << (8 * sizeof(int) - 16))); + } + + ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1], + nsamples, mp3buf, mp3buf_size); + + free(in_buffer[0]); + free(in_buffer[1]); + return ret; + +} + + + + +int +lame_encode_buffer_long2(lame_global_flags * gfp, + const long buffer_l[], + const long buffer_r[], + const int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int ret, i; + sample_t *in_buffer[2]; + + if (gfc->Class_ID != LAME_ID) + return -3; + + if (nsamples == 0) + return 0; + + in_buffer[0] = calloc(sizeof(sample_t), nsamples); + in_buffer[1] = calloc(sizeof(sample_t), nsamples); + + if (in_buffer[0] == NULL || in_buffer[1] == NULL) { + ERRORF(gfc, "Error: can't allocate in_buffer buffer\n"); + return -2; + } + + /* make a copy of input buffer, changing type to sample_t */ + for (i = 0; i < nsamples; i++) { + /* internal code expects +/- 32768.0 */ + in_buffer[0][i] = buffer_l[i] * (1.0 / ( 1 << (8 * sizeof(long) - 16))); + in_buffer[1][i] = buffer_r[i] * (1.0 / ( 1 << (8 * sizeof(long) - 16))); + } + + ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1], + nsamples, mp3buf, mp3buf_size); + + free(in_buffer[0]); + free(in_buffer[1]); + return ret; + +} + + + +int +lame_encode_buffer_long(lame_global_flags * gfp, + const long buffer_l[], + const long buffer_r[], + const int nsamples, unsigned char *mp3buf, const int mp3buf_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int ret, i; + sample_t *in_buffer[2]; + + if (gfc->Class_ID != LAME_ID) + return -3; + + if (nsamples == 0) + return 0; + + in_buffer[0] = calloc(sizeof(sample_t), nsamples); + in_buffer[1] = calloc(sizeof(sample_t), nsamples); + + if (in_buffer[0] == NULL || in_buffer[1] == NULL) { + ERRORF(gfc, "Error: can't allocate in_buffer buffer\n"); + return -2; + } + + /* make a copy of input buffer, changing type to sample_t */ + for (i = 0; i < nsamples; i++) { + in_buffer[0][i] = buffer_l[i]; + in_buffer[1][i] = buffer_r[i]; + } + + ret = lame_encode_buffer_sample_t(gfp,in_buffer[0],in_buffer[1], + nsamples, mp3buf, mp3buf_size); + + free(in_buffer[0]); + free(in_buffer[1]); + return ret; +} + + + + + + + + + + + +int +lame_encode_buffer_interleaved(lame_global_flags * gfp, + short int buffer[], + int nsamples, + unsigned char *mp3buf, int mp3buf_size) +{ + int ret, i; + short int *buffer_l; + short int *buffer_r; + + buffer_l = malloc(sizeof(short int) * nsamples); + buffer_r = malloc(sizeof(short int) * nsamples); + if (buffer_l == NULL || buffer_r == NULL) { + return -2; + } + for (i = 0; i < nsamples; i++) { + buffer_l[i] = buffer[2 * i]; + buffer_r[i] = buffer[2 * i + 1]; + } + ret = + lame_encode_buffer(gfp, buffer_l, buffer_r, nsamples, mp3buf, + mp3buf_size); + free(buffer_l); + free(buffer_r); + return ret; + +} + + +/*}}}*/ +/* int lame_encode (lame_global_flags* gfp, short int in_buffer[2][1152], char* mp3buf, int size ) *//*{{{ */ + + +/* old LAME interface. use lame_encode_buffer instead */ + +int +lame_encode(lame_global_flags * const gfp, + const short int in_buffer[2][1152], + unsigned char *const mp3buf, const int size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + + if (gfc->Class_ID != LAME_ID) + return -3; + + return lame_encode_buffer(gfp, in_buffer[0], in_buffer[1], gfp->framesize, + mp3buf, size); +} + +/*}}}*/ +/* int lame_encode_flush (lame_global_flags* gfp, char* mp3buffer, int mp3buffer_size ) *//*{{{ */ + + + +/***************************************************************** + Flush mp3 buffer, pad with ancillary data so last frame is complete. + Reset reservoir size to 0 + but keep all PCM samples and MDCT data in memory + This option is used to break a large file into several mp3 files + that when concatenated together will decode with no gaps + Because we set the reservoir=0, they will also decode seperately + with no errors. +*********************************************************************/ +int +lame_encode_flush_nogap(lame_global_flags * gfp, + unsigned char *mp3buffer, int mp3buffer_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + flush_bitstream(gfp); + return copy_buffer(gfc,mp3buffer, mp3buffer_size,1); +} + + +/* called by lame_init_params. You can also call this after flush_nogap + if you want to write new id3v2 and Xing VBR tags into the bitstream */ +int +lame_init_bitstream(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int i; + gfp->frameNum=0; + + if (!gfp->ogg) + id3tag_write_v2(gfp); + + /* initialize histogram data optionally used by frontend */ + for ( i = 0; i < 16; i++ ) + gfc->bitrate_stereoMode_Hist [i] [0] = + gfc->bitrate_stereoMode_Hist [i] [1] = + gfc->bitrate_stereoMode_Hist [i] [2] = + gfc->bitrate_stereoMode_Hist [i] [3] = + gfc->bitrate_stereoMode_Hist [i] [4] = 0; + + /* Write initial VBR Header to bitstream and init VBR data */ + if (gfp->bWriteVbrTag) + InitVbrTag(gfp); + + + return 0; +} + + +/*****************************************************************/ +/* flush internal PCM sample buffers, then mp3 buffers */ +/* then write id3 v1 tags into bitstream. */ +/*****************************************************************/ + +int +lame_encode_flush(lame_global_flags * gfp, + unsigned char *mp3buffer, int mp3buffer_size) +{ + lame_internal_flags *gfc = gfp->internal_flags; + short int buffer[2][1152]; + int imp3 = 0, mp3count, mp3buffer_size_remaining; + + /* we always add POSTDELAY=288 padding to make sure granule with real + * data can be complety decoded (because of 50% overlap with next granule */ + int end_padding=POSTDELAY; + + memset(buffer, 0, sizeof(buffer)); + mp3count = 0; + + + while (gfc->mf_samples_to_encode > 0) { + + mp3buffer_size_remaining = mp3buffer_size - mp3count; + + /* if user specifed buffer size = 0, dont check size */ + if (mp3buffer_size == 0) + mp3buffer_size_remaining = 0; + + /* send in a frame of 0 padding until all internal sample buffers + * are flushed + */ + imp3 = lame_encode_buffer(gfp, buffer[0], buffer[1], gfp->framesize, + mp3buffer, mp3buffer_size_remaining); + + /* don't count the above padding: */ + gfc->mf_samples_to_encode -= gfp->framesize; + if (gfc->mf_samples_to_encode < 0) { + /* we added extra padding to the end */ + end_padding += -gfc->mf_samples_to_encode; + } + + + if (imp3 < 0) { + /* some type of fatal error */ + return imp3; + } + mp3buffer += imp3; + mp3count += imp3; + } + + mp3buffer_size_remaining = mp3buffer_size - mp3count; + /* if user specifed buffer size = 0, dont check size */ + if (mp3buffer_size == 0) + mp3buffer_size_remaining = 0; + + if (gfp->ogg) { +#ifdef HAVE_VORBIS_ENCODER + /* ogg related stuff */ + imp3 = lame_encode_ogg_finish(gfp, mp3buffer, mp3buffer_size_remaining); +#endif + } + else { + /* mp3 related stuff. bit buffer might still contain some mp3 data */ + flush_bitstream(gfp); + imp3 = copy_buffer(gfc,mp3buffer, mp3buffer_size_remaining, 1); + if (imp3 < 0) { + /* some type of fatal error */ + return imp3; + } + mp3buffer += imp3; + mp3count += imp3; + mp3buffer_size_remaining = mp3buffer_size - mp3count; + /* if user specifed buffer size = 0, dont check size */ + if (mp3buffer_size == 0) + mp3buffer_size_remaining = 0; + + + /* write a id3 tag to the bitstream */ + id3tag_write_v1(gfp); + imp3 = copy_buffer(gfc,mp3buffer, mp3buffer_size_remaining, 0); + } + + if (imp3 < 0) { + return imp3; + } + mp3count += imp3; + gfp->encoder_padding=end_padding; + return mp3count; +} + +/*}}}*/ +/* void lame_close (lame_global_flags *gfp) *//*{{{ */ + +/*********************************************************************** + * + * lame_close () + * + * frees internal buffers + * + ***********************************************************************/ + +int +lame_close(lame_global_flags * gfp) +{ + lame_internal_flags *gfc = gfp->internal_flags; + + if (gfc->Class_ID != LAME_ID) + return -3; + + gfc->Class_ID = 0; + + // this routien will free all malloc'd data in gfc, and then free gfc: + freegfc(gfc); + + gfp->internal_flags = NULL; + + if (gfp->lame_allocated_gfp) + free(gfp); + + return 0; +} + + +/*}}}*/ +/* int lame_encode_finish (lame_global_flags* gfp, char* mp3buffer, int mp3buffer_size ) *//*{{{ */ + + +/*****************************************************************/ +/* flush internal mp3 buffers, and free internal buffers */ +/*****************************************************************/ + +int +lame_encode_finish(lame_global_flags * gfp, + unsigned char *mp3buffer, int mp3buffer_size) +{ + int ret = lame_encode_flush(gfp, mp3buffer, mp3buffer_size); + + lame_close(gfp); + + return ret; +} + +/*}}}*/ +/* void lame_mp3_tags_fid (lame_global_flags *gfp,FILE *fpStream) *//*{{{ */ + +/*****************************************************************/ +/* write VBR Xing header, and ID3 version 1 tag, if asked for */ +/*****************************************************************/ +void +lame_mp3_tags_fid(lame_global_flags * gfp, FILE * fpStream) +{ + if (gfp->bWriteVbrTag) { + /* Map VBR_q to Xing quality value: 0=worst, 100=best */ + int nQuality = ((9-gfp->VBR_q) * 100) / 9; + + /* Write Xing header again */ + if (fpStream && !fseek(fpStream, 0, SEEK_SET)) + PutVbrTag(gfp, fpStream, nQuality); + } + + +} +/*}}}*/ +/* lame_global_flags *lame_init (void) *//*{{{ */ + +lame_global_flags * +lame_init(void) +{ + lame_global_flags *gfp; + int ret; + + gfp = calloc(1, sizeof(lame_global_flags)); + if (gfp == NULL) + return NULL; + + ret = lame_init_old(gfp); + if (ret != 0) { + free(gfp); + return NULL; + } + + gfp->lame_allocated_gfp = 1; + return gfp; +} + +/*}}}*/ +/* int lame_init_old (lame_global_flags *gfp) *//*{{{ */ + +/* initialize mp3 encoder */ +int +lame_init_old(lame_global_flags * gfp) +{ + lame_internal_flags *gfc; + + disable_FPE(); // disable floating point exceptions + + memset(gfp, 0, sizeof(lame_global_flags)); + + if (NULL == + (gfc = gfp->internal_flags = + calloc(1, sizeof(lame_internal_flags)))) return -1; + + /* Global flags. set defaults here for non-zero values */ + /* see lame.h for description */ + /* set integer values to -1 to mean that LAME will compute the + * best value, UNLESS the calling program as set it + * (and the value is no longer -1) + */ + + + gfp->mode = NOT_SET; + gfp->original = 1; + gfp->in_samplerate = 1000 * 44.1; + gfp->num_channels = 2; + gfp->num_samples = MAX_U_32_NUM; + + gfp->bWriteVbrTag = 1; + gfp->quality = -1; + gfp->short_blocks = short_block_not_set; + + gfp->lowpassfreq = 0; + gfp->highpassfreq = 0; + gfp->lowpasswidth = -1; + gfp->highpasswidth = -1; + + gfp->padding_type = PAD_ADJUST; + gfp->VBR = vbr_off; + gfp->VBR_q = 4; + gfp->VBR_mean_bitrate_kbps = 128; + gfp->VBR_min_bitrate_kbps = 0; + gfp->VBR_max_bitrate_kbps = 0; + gfp->VBR_hard_min = 0; + + + gfc->resample_ratio = 1; + gfc->lowpass_band = 32; + gfc->highpass_band = -1; + gfc->VBR_min_bitrate = 1; /* not 0 ????? */ + gfc->VBR_max_bitrate = 13; /* not 14 ????? */ + + gfc->OldValue[0] = 180; + gfc->OldValue[1] = 180; + gfc->CurrentStep = 4; + gfc->masking_lower = 1; + + gfp->athaa_type = -1; + gfp->ATHtype = -1; /* default = -1 = set in lame_init_params */ + gfp->athaa_loudapprox = -1; /* 1 = flat loudness approx. (total energy) */ + /* 2 = equal loudness curve */ + gfp->athaa_sensitivity = 0.0; /* no offset */ + gfp->useTemporal = -1; + + /* The reason for + * int mf_samples_to_encode = ENCDELAY + POSTDELAY; + * ENCDELAY = internal encoder delay. And then we have to add POSTDELAY=288 + * because of the 50% MDCT overlap. A 576 MDCT granule decodes to + * 1152 samples. To synthesize the 576 samples centered under this granule + * we need the previous granule for the first 288 samples (no problem), and + * the next granule for the next 288 samples (not possible if this is last + * granule). So we need to pad with 288 samples to make sure we can + * encode the 576 samples we are interested in. + */ + gfc->mf_samples_to_encode = ENCDELAY + POSTDELAY; + gfp->encoder_padding = 0; + gfc->mf_size = ENCDELAY - MDCTDELAY; /* we pad input with this many 0's */ + +#ifdef KLEMM_44 + /* XXX: this wasn't protectes by KLEMM_44 initially! */ + gfc->last_ampl = gfc->ampl = +1.0; +#endif + return 0; +} + +/*}}}*/ + +/*********************************************************************** + * + * some simple statistics + * + * Robert Hegemann 2000-10-11 + * + ***********************************************************************/ + +/* histogram of used bitrate indexes: + * One has to weight them to calculate the average bitrate in kbps + * + * bitrate indices: + * there are 14 possible bitrate indices, 0 has the special meaning + * "free format" which is not possible to mix with VBR and 15 is forbidden + * anyway. + * + * stereo modes: + * 0: LR number of left-right encoded frames + * 1: LR-I number of left-right and intensity encoded frames + * 2: MS number of mid-side encoded frames + * 3: MS-I number of mid-side and intensity encoded frames + * + * 4: number of encoded frames + * + */ + +void +lame_bitrate_hist(const lame_global_flags * const gfp, int bitrate_count[14]) +{ + const lame_internal_flags *gfc; + int i; + + if (NULL == bitrate_count) + return; + if (NULL == gfp) + return; + gfc = gfp->internal_flags; + if (NULL == gfc) + return; + + for (i = 0; i < 14; i++) + bitrate_count[i] = gfc->bitrate_stereoMode_Hist[i + 1][4]; +} + + +void +lame_bitrate_kbps(const lame_global_flags * const gfp, int bitrate_kbps[14]) +{ + const lame_internal_flags *gfc; + int i; + + if (NULL == bitrate_kbps) + return; + if (NULL == gfp) + return; + gfc = gfp->internal_flags; + if (NULL == gfc) + return; + + for (i = 0; i < 14; i++) + bitrate_kbps[i] = bitrate_table[gfp->version][i + 1]; +} + + + +void +lame_stereo_mode_hist(const lame_global_flags * const gfp, int stmode_count[4]) +{ + const lame_internal_flags *gfc; + int i; + + if (NULL == stmode_count) + return; + if (NULL == gfp) + return; + gfc = gfp->internal_flags; + if (NULL == gfc) + return; + + for (i = 0; i < 4; i++) { + int j, sum = 0; + for (j = 0; j < 14; j++) + sum += gfc->bitrate_stereoMode_Hist[j + 1][i]; + stmode_count[i] = sum; + } +} + + + +void +lame_bitrate_stereo_mode_hist(const lame_global_flags * const gfp, + int bitrate_stmode_count[14][4]) +{ + const lame_internal_flags *gfc; + int i; + int j; + + if (NULL == bitrate_stmode_count) + return; + if (NULL == gfp) + return; + gfc = gfp->internal_flags; + if (NULL == gfc) + return; + + for (j = 0; j < 14; j++) + for (i = 0; i < 4; i++) + bitrate_stmode_count[j][i] = gfc->bitrate_stereoMode_Hist[j + 1][i]; +} + +/* end of lame.c */ diff --git a/lib/lame/lame.h b/lib/lame/lame.h new file mode 100644 index 0000000..3354ec7 --- /dev/null +++ b/lib/lame/lame.h @@ -0,0 +1,902 @@ +/* + * Interface to MP3 LAME encoding engine + * + * Copyright (c) 1999 Mark Taylor + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* $Id: lame.h,v 1.1 2002/04/28 17:30:20 kramm Exp $ */ + +#ifndef LAME_LAME_H +#define LAME_LAME_H + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +#if defined(WIN32) +#undef CDECL +#define CDECL _cdecl +#else +#define CDECL +#endif + + +typedef enum vbr_mode_e { + vbr_off=0, + vbr_mt, /* obsolete, same as vbr_mtrh */ + vbr_rh, + vbr_abr, + vbr_mtrh, + vbr_max_indicator, /* Don't use this! It's used for sanity checks. */ + vbr_default=vbr_rh /* change this to change the default VBR mode of LAME */ +} vbr_mode; + + +/* MPEG modes */ +typedef enum MPEG_mode_e { + STEREO = 0, + JOINT_STEREO, + DUAL_CHANNEL, /* LAME doesn't supports this! */ + MONO, + NOT_SET, + MAX_INDICATOR /* Don't use this! It's used for sanity checks. */ +} MPEG_mode; + +/* Padding types */ +typedef enum Padding_type_e { + PAD_NO = 0, + PAD_ALL, + PAD_ADJUST, + PAD_MAX_INDICATOR /* Don't use this! It's used for sanity checks. */ +} Padding_type; + + + +struct lame_global_struct; +typedef struct lame_global_struct lame_global_flags; +typedef lame_global_flags *lame_t; + + + + +/*********************************************************************** + * + * The LAME API + * These functions should be called, in this order, for each + * MP3 file to be encoded + * + ***********************************************************************/ + + +/* + * REQUIRED: + * initialize the encoder. sets default for all encoder paramters, + * returns -1 if some malloc()'s failed + * otherwise returns 0 + */ +lame_global_flags * CDECL lame_init(void); +/* obsolete version */ +int CDECL lame_init_old(lame_global_flags *); + + +/* + * OPTIONAL: + * set as needed to override defaults + */ + +/******************************************************************** + * input stream description + ***********************************************************************/ +// number of samples. default = 2^32-1 +int CDECL lame_set_num_samples(lame_global_flags *, unsigned long); +unsigned long CDECL lame_get_num_samples(const lame_global_flags *); + +// input sample rate in Hz. default = 44100hz +int CDECL lame_set_in_samplerate(lame_global_flags *, int); +int CDECL lame_get_in_samplerate(const lame_global_flags *); + +// number of channels in input stream. default=2 +int CDECL lame_set_num_channels(lame_global_flags *, int); +int CDECL lame_get_num_channels(const lame_global_flags *); + +// scale the input by this amount before encoding. default=0 (disabled) +// (not used by decoding routines) +int CDECL lame_set_scale(lame_global_flags *, float); +float CDECL lame_get_scale(const lame_global_flags *); + +// scale the channel 0 (left) input by this amount before encoding. +// default=0 (disabled) +// (not used by decoding routines) +int CDECL lame_set_scale_left(lame_global_flags *, float); +float CDECL lame_get_scale_left(const lame_global_flags *); + +// scale the channel 1 (right) input by this amount before encoding. +// default=0 (disabled) +// (not used by decoding routines) +int CDECL lame_set_scale_right(lame_global_flags *, float); +float CDECL lame_get_scale_right(const lame_global_flags *); + +// output sample rate in Hz. default = 0, which means LAME picks best value +// based on the amount of compression. MPEG only allows: +// MPEG1 32, 44.1, 48khz +// MPEG2 16, 22.05, 24 +// MPEG2.5 8, 11.025, 12 +// (not used by decoding routines) +int CDECL lame_set_out_samplerate(lame_global_flags *, int); +int CDECL lame_get_out_samplerate(const lame_global_flags *); + + +/******************************************************************** + * general control parameters + ***********************************************************************/ +// 1=cause LAME to collect data for an MP3 frame analyzer. default=0 +int CDECL lame_set_analysis(lame_global_flags *, int); +int CDECL lame_get_analysis(const lame_global_flags *); + +// 1 = write a Xing VBR header frame. +// default = 1 for VBR/ABR modes, 0 for CBR mode +// this variable must have been added by a Hungarian notation Windows programmer :-) +int CDECL lame_set_bWriteVbrTag(lame_global_flags *, int); +int CDECL lame_get_bWriteVbrTag(const lame_global_flags *); + +// 1=decode only. use lame/mpglib to convert mp3/ogg to wav. default=0 +int CDECL lame_set_decode_only(lame_global_flags *, int); +int CDECL lame_get_decode_only(const lame_global_flags *); + +// 1=encode a Vorbis .ogg file. default=0 +int CDECL lame_set_ogg(lame_global_flags *, int); +int CDECL lame_get_ogg(const lame_global_flags *); + +// internal algorithm selection. True quality is determined by the bitrate +// but this variable will effect quality by selecting expensive or cheap algorithms. +// quality=0..9. 0=best (very slow). 9=worst. +// recommended: 2 near-best quality, not too slow +// 5 good quality, fast +// 7 ok quality, really fast +int CDECL lame_set_quality(lame_global_flags *, int); +int CDECL lame_get_quality(const lame_global_flags *); + +// mode = 0,1,2,3 = stereo, jstereo, dual channel (not supported), mono +// default: lame picks based on compression ration and input channels +int CDECL lame_set_mode(lame_global_flags *, MPEG_mode); +MPEG_mode CDECL lame_get_mode(const lame_global_flags *); + +// mode_automs. Use a M/S mode with a switching threshold based on +// compression ratio +// default = 0 (disabled) +int CDECL lame_set_mode_automs(lame_global_flags *, int); +int CDECL lame_get_mode_automs(const lame_global_flags *); + +// force_ms. Force M/S for all frames. For testing only. +// default = 0 (disabled) +int CDECL lame_set_force_ms(lame_global_flags *, int); +int CDECL lame_get_force_ms(const lame_global_flags *); + +// use free_format? default = 0 (disabled) +int CDECL lame_set_free_format(lame_global_flags *, int); +int CDECL lame_get_free_format(const lame_global_flags *); + +/* + * OPTIONAL: + * Set printf like error/debug/message reporting functions. + * The second argument has to be a pointer to a function which looks like + * void my_debugf(const char *format, va_list ap) + * { + * (void) vfprintf(stdout, format, ap); + * } + * If you use NULL as the value of the pointer in the set function, the + * lame buildin function will be used (prints to stderr). + * To quiet any output you have to replace the body of the example function + * with just "return;" and use it in the set function. + */ +int CDECL lame_set_errorf(lame_global_flags *, + void (*func)(const char *, va_list)); +int CDECL lame_set_debugf(lame_global_flags *, + void (*func)(const char *, va_list)); +int CDECL lame_set_msgf (lame_global_flags *, + void (*func)(const char *, va_list)); + + + +/* set one of brate compression ratio. default is compression ratio of 11. */ +int CDECL lame_set_brate(lame_global_flags *, int); +int CDECL lame_get_brate(const lame_global_flags *); +int CDECL lame_set_compression_ratio(lame_global_flags *, float); +float CDECL lame_get_compression_ratio(const lame_global_flags *); + +/******************************************************************** + * frame params + ***********************************************************************/ +// mark as copyright. default=0 +int CDECL lame_set_copyright(lame_global_flags *, int); +int CDECL lame_get_copyright(const lame_global_flags *); + +// mark as original. default=1 +int CDECL lame_set_original(lame_global_flags *, int); +int CDECL lame_get_original(const lame_global_flags *); + +// error_protection. Use 2 bytes from each frame for CRC checksum. default=0 +int CDECL lame_set_error_protection(lame_global_flags *, int); +int CDECL lame_get_error_protection(const lame_global_flags *); + +// padding_type. 0=pad no frames 1=pad all frames 2=adjust padding(default) +int CDECL lame_set_padding_type(lame_global_flags *, Padding_type); +Padding_type CDECL lame_get_padding_type(const lame_global_flags *); + +// MP3 'private extension' bit Meaningless. default=0 +int CDECL lame_set_extension(lame_global_flags *, int); +int CDECL lame_get_extension(const lame_global_flags *); + +// enforce strict ISO compliance. default=0 +int CDECL lame_set_strict_ISO(lame_global_flags *, int); +int CDECL lame_get_strict_ISO(const lame_global_flags *); + + +/******************************************************************** + * quantization/noise shaping + ***********************************************************************/ + +// disable the bit reservoir. For testing only. default=0 +int CDECL lame_set_disable_reservoir(lame_global_flags *, int); +int CDECL lame_get_disable_reservoir(const lame_global_flags *); + +// select a different "best quantization" function. default=0 +int CDECL lame_set_experimentalX(lame_global_flags *, int); +int CDECL lame_get_experimentalX(const lame_global_flags *); + +// another experimental option. for testing only +int CDECL lame_set_experimentalY(lame_global_flags *, int); +int CDECL lame_get_experimentalY(const lame_global_flags *); + +// another experimental option. for testing only +int CDECL lame_set_experimentalZ(lame_global_flags *, int); +int CDECL lame_get_experimentalZ(const lame_global_flags *); + +// Naoki's psycho acoustic model. default=0 +int CDECL lame_set_exp_nspsytune(lame_global_flags *, int); +int CDECL lame_get_exp_nspsytune(const lame_global_flags *); + + + +/******************************************************************** + * VBR control + ***********************************************************************/ +// Types of VBR. default = vbr_off = CBR +int CDECL lame_set_VBR(lame_global_flags *, vbr_mode); +vbr_mode CDECL lame_get_VBR(const lame_global_flags *); + +// VBR quality level. 0=highest 9=lowest +int CDECL lame_set_VBR_q(lame_global_flags *, int); +int CDECL lame_get_VBR_q(const lame_global_flags *); + +// Ignored except for VBR=vbr_abr (ABR mode) +int CDECL lame_set_VBR_mean_bitrate_kbps(lame_global_flags *, int); +int CDECL lame_get_VBR_mean_bitrate_kbps(const lame_global_flags *); + +int CDECL lame_set_VBR_min_bitrate_kbps(lame_global_flags *, int); +int CDECL lame_get_VBR_min_bitrate_kbps(const lame_global_flags *); + +int CDECL lame_set_VBR_max_bitrate_kbps(lame_global_flags *, int); +int CDECL lame_get_VBR_max_bitrate_kbps(const lame_global_flags *); + +// 1=stricetly enforce VBR_min_bitrate. Normally it will be violated for +// analog silence +int CDECL lame_set_VBR_hard_min(lame_global_flags *, int); +int CDECL lame_get_VBR_hard_min(const lame_global_flags *); + + +/******************************************************************** + * Filtering control + ***********************************************************************/ +// freq in Hz to apply lowpass. Default = 0 = lame chooses. -1 = disabled +int CDECL lame_set_lowpassfreq(lame_global_flags *, int); +int CDECL lame_get_lowpassfreq(const lame_global_flags *); +// width of transition band, in Hz. Default = one polyphase filter band +int CDECL lame_set_lowpasswidth(lame_global_flags *, int); +int CDECL lame_get_lowpasswidth(const lame_global_flags *); + +// freq in Hz to apply highpass. Default = 0 = lame chooses. -1 = disabled +int CDECL lame_set_highpassfreq(lame_global_flags *, int); +int CDECL lame_get_highpassfreq(const lame_global_flags *); +// width of transition band, in Hz. Default = one polyphase filter band +int CDECL lame_set_highpasswidth(lame_global_flags *, int); +int CDECL lame_get_highpasswidth(const lame_global_flags *); + + +/******************************************************************** + * psycho acoustics and other arguments which you should not change + * unless you know what you are doing + ***********************************************************************/ +// only use ATH for masking +int CDECL lame_set_ATHonly(lame_global_flags *, int); +int CDECL lame_get_ATHonly(const lame_global_flags *); + +// only use ATH for short blocks +int CDECL lame_set_ATHshort(lame_global_flags *, int); +int CDECL lame_get_ATHshort(const lame_global_flags *); + +// disable ATH +int CDECL lame_set_noATH(lame_global_flags *, int); +int CDECL lame_get_noATH(const lame_global_flags *); + +// select ATH formula +int CDECL lame_set_ATHtype(lame_global_flags *, int); +int CDECL lame_get_ATHtype(const lame_global_flags *); + +// lower ATH by this many db +int CDECL lame_set_ATHlower(lame_global_flags *, float); +float CDECL lame_get_ATHlower(const lame_global_flags *); + +// select ATH adaptive adjustment type +int CDECL lame_set_athaa_type( lame_global_flags *, int); +int CDECL lame_get_athaa_type( const lame_global_flags *); + +// select the loudness approximation used by the ATH adaptive auto-leveling +int CDECL lame_set_athaa_loudapprox( lame_global_flags *, int); +int CDECL lame_get_athaa_loudapprox( const lame_global_flags *); + +// adjust (in dB) the point below which adaptive ATH level adjustment occurs +int CDECL lame_set_athaa_sensitivity( lame_global_flags *, float); +float CDECL lame_get_athaa_sensitivity( const lame_global_flags* ); + +// predictability limit (ISO tonality formula) +int CDECL lame_set_cwlimit(lame_global_flags *, int); +int CDECL lame_get_cwlimit(const lame_global_flags *); + +// allow blocktypes to differ between channels? +// default: 0 for jstereo, 1 for stereo +int CDECL lame_set_allow_diff_short(lame_global_flags *, int); +int CDECL lame_get_allow_diff_short(const lame_global_flags *); + +// use temporal masking effect (default = 1) +int CDECL lame_set_useTemporal(lame_global_flags *, int); +int CDECL lame_get_useTemporal(const lame_global_flags *); + +// disable short blocks +int CDECL lame_set_no_short_blocks(lame_global_flags *, int); +int CDECL lame_get_no_short_blocks(const lame_global_flags *); + +// force short blocks +int CDECL lame_set_force_short_blocks(lame_global_flags *, int); +int CDECL lame_get_force_short_blocks(const lame_global_flags *); + +/* Input PCM is emphased PCM (for instance from one of the rarely + emphased CDs), it is STRONGLY not recommended to use this, because + psycho does not take it into account, and last but not least many decoders + ignore these bits */ +int CDECL lame_set_emphasis(lame_global_flags *, int); +int CDECL lame_get_emphasis(const lame_global_flags *); + + + +/************************************************************************/ +/* internal variables, cannot be set... */ +/* provided because they may be of use to calling application */ +/************************************************************************/ +// version 0=MPEG-2 1=MPEG-1 (2=MPEG-2.5) +int CDECL lame_get_version(const lame_global_flags *); + +// encoder delay +int CDECL lame_get_encoder_delay(const lame_global_flags *); + +// padding appended to the input to make sure decoder can fully decode +// all input. Note that this value can only be calculated during the +// call to lame_encoder_flush(). Before lame_encoder_flush() has +// been called, the value of encoder_padding = 0. +int CDECL lame_get_encoder_padding(const lame_global_flags *); + +// size of MPEG frame +int CDECL lame_get_framesize(const lame_global_flags *); + +// number of PCM samples buffered, but not yet encoded to mp3 data. +int CDECL lame_get_mf_samples_to_encode( const lame_global_flags* gfp ); + +// size (bytes) of mp3 data buffered, but not yet encoded. +// this is the number of bytes which would be output by a call to +// lame_encode_flush_nogap. NOTE: lame_encode_flush() will return +// more bytes than this because it will encode the reamining buffered +// PCM samples before flushing the mp3 buffers. +int CDECL lame_get_size_mp3buffer( const lame_global_flags* gfp ); + +// number of frames encoded so far +int CDECL lame_get_frameNum(const lame_global_flags *); + +// lame's estimate of the total number of frames to be encoded +// only valid if calling program set num_samples +int CDECL lame_get_totalframes(const lame_global_flags *); + + + + + + + + +/* + * REQUIRED: + * sets more internal configuration based on data provided above. + * returns -1 if something failed. + */ +int CDECL lame_init_params(lame_global_flags * const ); + + +/* + * OPTIONAL: + * get the version number, in a string. of the form: + * "3.63 (beta)" or just "3.63". + */ +const char* CDECL get_lame_version ( void ); +const char* CDECL get_lame_short_version ( void ); +const char* CDECL get_lame_very_short_version ( void ); +const char* CDECL get_psy_version ( void ); +const char* CDECL get_lame_url ( void ); + +/* + * OPTIONAL: + * get the version numbers in numerical form. + */ +typedef struct { + /* generic LAME version */ + int major; + int minor; + int alpha; /* 0 if not an alpha version */ + int beta; /* 0 if not a beta version */ + + /* version of the psy model */ + int psy_major; + int psy_minor; + int psy_alpha; /* 0 if not an alpha version */ + int psy_beta; /* 0 if not a beta version */ + + /* compile time features */ + const char *features; /* Don't make assumptions about the contents! */ +} lame_version_t; +void CDECL get_lame_version_numerical ( lame_version_t *const ); + + +/* + * OPTIONAL: + * print internal lame configuration to message handler + */ +void CDECL lame_print_config(const lame_global_flags* gfp); + +void CDECL lame_print_internals( const lame_global_flags *gfp); + + +/* + * input pcm data, output (maybe) mp3 frames. + * This routine handles all buffering, resampling and filtering for you. + * + * return code number of bytes output in mp3buf. Can be 0 + * -1: mp3buf was too small + * -2: malloc() problem + * -3: lame_init_params() not called + * -4: psycho acoustic problems + * -5: ogg cleanup encoding error + * -6: ogg frame encoding error + * + * The required mp3buf_size can be computed from num_samples, + * samplerate and encoding rate, but here is a worst case estimate: + * + * mp3buf_size in bytes = 1.25*num_samples + 7200 + * + * I think a tighter bound could be: (mt, March 2000) + * MPEG1: + * num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512 + * MPEG2: + * num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256 + * + * but test first if you use that! + * + * set mp3buf_size = 0 and LAME will not check if mp3buf_size is + * large enough. + * + * NOTE: + * if gfp->num_channels=2, but gfp->mode = 3 (mono), the L & R channels + * will be averaged into the L channel before encoding only the L channel + * This will overwrite the data in buffer_l[] and buffer_r[]. + * +*/ +int CDECL lame_encode_buffer ( + lame_global_flags* gfp, /* global context handle */ + const short int buffer_l [], /* PCM data for left channel */ + const short int buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* + * as above, but input has L & R channel data interleaved. + * NOTE: + * num_samples = number of samples in the L (or R) + * channel, not the total number of samples in pcm[] + */ +int CDECL lame_encode_buffer_interleaved( + lame_global_flags* gfp, /* global context handlei */ + short int pcm[], /* PCM data for left and right + channel, interleaved */ + int num_samples, /* number of samples per channel, + _not_ number of samples in + pcm[] */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + int mp3buf_size ); /* number of valid octets in this + stream */ + + +/* as lame_encode_buffer, but for 'float's. + * !! NOTE: !! data must still be scaled to be in the same range as + * short int, +/- 32768 + */ +int CDECL lame_encode_buffer_float( + lame_global_flags* gfp, /* global context handle */ + const float buffer_l [], /* PCM data for left channel */ + const float buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + + +/* as lame_encode_buffer, but for long's + * !! NOTE: !! data must still be scaled to be in the same range as + * short int, +/- 32768 + * + * This scaling was a mistake (doesn't allow one to exploit full + * precision of type 'long'. Use lame_encode_buffer_long2() instead. + * + */ +int CDECL lame_encode_buffer_long( + lame_global_flags* gfp, /* global context handle */ + const long buffer_l [], /* PCM data for left channel */ + const long buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* Same as lame_encode_buffer_long(), but with correct scaling. + * !! NOTE: !! data must still be scaled to be in the same range as + * type 'long'. Data should be in the range: +/- 2^(8*size(long)-1) + * + */ +int CDECL lame_encode_buffer_long2( + lame_global_flags* gfp, /* global context handle */ + const long buffer_l [], /* PCM data for left channel */ + const long buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + +/* as lame_encode_buffer, but for int's + * !! NOTE: !! input should be scaled to the maximum range of 'int' + * If int is 4 bytes, then the values should range from + * +/- 2147483648. + * + * This routine does not (and cannot, without loosing precision) use + * the same scaling as the rest of the lame_encode_buffer() routines. + * + */ +int CDECL lame_encode_buffer_int( + lame_global_flags* gfp, /* global context handle */ + const int buffer_l [], /* PCM data for left channel */ + const int buffer_r [], /* PCM data for right channel */ + const int nsamples, /* number of samples per channel */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + const int mp3buf_size ); /* number of valid octets in this + stream */ + + + + + +/* + * REQUIRED: + * lame_encode_flush will flush the intenal PCM buffers, padding with + * 0's to make sure the final frame is complete, and then flush + * the internal MP3 buffers, and thus may return a + * final few mp3 frames. 'mp3buf' should be at least 7200 bytes long + * to hold all possible emitted data. + * + * will also write id3v1 tags (if any) into the bitstream + * + * return code = number of bytes output to mp3buf. Can be 0 + */ +int CDECL lame_encode_flush( + lame_global_flags * gfp, /* global context handle */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + int size); /* number of valid octets in this stream */ + +/* + * OPTIONAL: + * lame_encode_flush_nogap will flush the internal mp3 buffers and pad + * the last frame with ancillary data so it is a complete mp3 frame. + * + * 'mp3buf' should be at least 7200 bytes long + * to hold all possible emitted data. + * + * After a call to this routine, the outputed mp3 data is complete, but + * you may continue to encode new PCM samples and write future mp3 data + * to a different file. The two mp3 files will play back with no gaps + * if they are concatenated together. + * + * This routine will NOT write id3v1 tags into the bitstream. + * + * return code = number of bytes output to mp3buf. Can be 0 + */ +int CDECL lame_encode_flush_nogap( + lame_global_flags * gfp, /* global context handle */ + unsigned char* mp3buf, /* pointer to encoded MP3 stream */ + int size); /* number of valid octets in this stream */ + +/* + * OPTIONAL: + * Normally, this is called by lame_init_params(). It writes id3v2 and + * Xing headers into the front of the bitstream, and sets frame counters + * and bitrate histogram data to 0. You can also call this after + * lame_encode_flush_nogap(). + */ +int CDECL lame_init_bitstream( + lame_global_flags * gfp); /* global context handle */ + + + +/* + * OPTIONAL: some simple statistics + * a bitrate histogram to visualize the distribution of used frame sizes + * a stereo mode histogram to visualize the distribution of used stereo + * modes, useful in joint-stereo mode only + * 0: LR left-right encoded + * 1: LR-I left-right and intensity encoded (currently not supported) + * 2: MS mid-side encoded + * 3: MS-I mid-side and intensity encoded (currently not supported) + * + * attention: don't call them after lame_encode_finish + * suggested: lame_encode_flush -> lame_*_hist -> lame_close + */ + +void CDECL lame_bitrate_hist( + const lame_global_flags *const gfp, + int bitrate_count[14] ); +void CDECL lame_bitrate_kbps( + const lame_global_flags *const gfp, + int bitrate_kbps [14] ); +void CDECL lame_stereo_mode_hist( + const lame_global_flags *const gfp, + int stereo_mode_count[4] ); + +void CDECL lame_bitrate_stereo_mode_hist ( + const lame_global_flags * const gfp, + int bitrate_stmode_count [14] [4] ); + + +/* + * OPTIONAL: + * lame_mp3_tags_fid will append a Xing VBR tag to the mp3 file with file + * pointer fid. These calls perform forward and backwards seeks, so make + * sure fid is a real file. Make sure lame_encode_flush has been called, + * and all mp3 data has been written to the file before calling this + * function. + * NOTE: + * if VBR tags are turned off by the user, or turned off by LAME because + * the output is not a regular file, this call does nothing +*/ +void CDECL lame_mp3_tags_fid(lame_global_flags *,FILE* fid); + + +/* + * REQUIRED: + * final call to free all remaining buffers + */ +int CDECL lame_close (lame_global_flags *); + +/* + * OBSOLETE: + * lame_encode_finish combines lame_encode_flush() and lame_close() in + * one call. However, once this call is made, the statistics routines + * will no longer work because the data will have been cleared + */ +int CDECL lame_encode_finish( + lame_global_flags* gfp, + unsigned char* mp3buf, + int size ); + + + + + + + +/********************************************************************* + * + * decoding + * + * a simple interface to mpglib, part of mpg123, is also included if + * libmp3lame is compiled with HAVE_MPGLIB + * + *********************************************************************/ +typedef struct { + int header_parsed; /* 1 if header was parsed and following data was + computed */ + int stereo; /* number of channels */ + int samplerate; /* sample rate */ + int bitrate; /* bitrate */ + int mode; /* mp3 frame type */ + int mode_ext; /* mp3 frame type */ + int framesize; /* number of samples per mp3 frame */ + + /* this data is only computed if mpglib detects a Xing VBR header */ + unsigned long nsamp; /* number of samples in mp3 file. */ + int totalframes; /* total number of frames in mp3 file */ + + /* this data is not currently computed by the mpglib routines */ + int framenum; /* frames decoded counter */ +} mp3data_struct; + + +/* required call to initialize decoder */ +int CDECL lame_decode_init(void); + +/********************************************************************* + * input 1 mp3 frame, output (maybe) pcm data. + * lame_decode() return code: + * -1: error + * 0: need more data + * n>0: size of pcm output + *********************************************************************/ +int CDECL lame_decode( + unsigned char * mp3buf, + int len, + short pcm_l[], + short pcm_r[] ); + +/* same as lame_decode, and also returns mp3 header data */ +int CDECL lame_decode_headers( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); + +/* same as lame_decode, but returns at most one frame */ +int CDECL lame_decode1( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[] ); + +/* same as lame_decode1, but returns at most one frame and mp3 header data */ +int CDECL lame_decode1_headers( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data ); + +/* same as lame_decode1_headers, but also returns enc_delay and enc_padding + from VBR Info tag, (-1 if no info tag was found) */ +int CDECL lame_decode1_headersB( + unsigned char* mp3buf, + int len, + short pcm_l[], + short pcm_r[], + mp3data_struct* mp3data, + int *enc_delay, + int *enc_padding ); + + + + + +/********************************************************************* + * + * id3tag stuff + * + *********************************************************************/ + +/* + * id3tag.h -- Interface to write ID3 version 1 and 2 tags. + * + * Copyright (C) 2000 Don Melton. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +/* utility to obtain alphabetically sorted list of genre names with numbers */ +extern void id3tag_genre_list( + void (*handler)(int, const char *, void *), + void* cookie); + +extern void id3tag_init (lame_global_flags *gfp); + +/* force addition of version 2 tag */ +extern void id3tag_add_v2 (lame_global_flags *gfp); + +/* add only a version 1 tag */ +extern void id3tag_v1_only (lame_global_flags *gfp); + +/* add only a version 2 tag */ +extern void id3tag_v2_only (lame_global_flags *gfp); + +/* pad version 1 tag with spaces instead of nulls */ +extern void id3tag_space_v1 (lame_global_flags *gfp); + +/* pad version 2 tag with extra 128 bytes */ +extern void id3tag_pad_v2 (lame_global_flags *gfp); + +extern void id3tag_set_title( + lame_global_flags* gfp, + const char* title ); +extern void id3tag_set_artist( + lame_global_flags* gfp, + const char* artist ); +extern void id3tag_set_album( + lame_global_flags* gfp, + const char* album ); +extern void id3tag_set_year( + lame_global_flags* gfp, + const char* year ); +extern void id3tag_set_comment( + lame_global_flags* gfp, + const char* comment ); +extern void id3tag_set_track( + lame_global_flags* gfp, + const char* track ); + +/* return non-zero result if genre name or number is invalid */ +extern int id3tag_set_genre( + lame_global_flags* gfp, + const char* genre ); + +/*********************************************************************** +* +* list of valid bitrates [kbps] & sample frequencies [Hz]. +* first index: 0: MPEG-2 values (sample frequencies 16...24 kHz) +* 1: MPEG-1 values (sample frequencies 32...48 kHz) +* 2: MPEG-2.5 values (sample frequencies 8...12 kHz) +***********************************************************************/ +extern const int bitrate_table [3] [16]; +extern const int samplerate_table [3] [ 4]; + + + +/* maximum size of mp3buffer needed if you encode at most 1152 samples for + each call to lame_encode_buffer. see lame_encode_buffer() below + (LAME_MAXMP3BUFFER is now obsolete) */ +#define LAME_MAXMP3BUFFER 16384 + + +#if defined(__cplusplus) +} +#endif +#endif /* LAME_LAME_H */ diff --git a/lib/lame/lame_global_flags.h b/lib/lame/lame_global_flags.h new file mode 100644 index 0000000..7267c93 --- /dev/null +++ b/lib/lame/lame_global_flags.h @@ -0,0 +1,178 @@ + +#ifndef LAME_GLOBAL_FLAGS_H +#define LAME_GLOBAL_FLAGS_H + +struct lame_internal_flags; +typedef struct lame_internal_flags lame_internal_flags; + + +typedef enum short_block_e { + short_block_not_set = -1, /* allow LAME to decide */ + short_block_allowed = 0, /* LAME may use them, even different block types for L/R */ + short_block_coupled, /* LAME may use them, but always same block types in L/R */ + short_block_dispensed, /* LAME will not use short blocks, long blocks only */ + short_block_forced /* LAME will not use long blocks, short blocks only */ +} short_block_t; + +/*********************************************************************** +* +* Control Parameters set by User. These parameters are here for +* backwards compatibility with the old, non-shared lib API. +* Please use the lame_set_variablename() functions below +* +* +***********************************************************************/ +struct lame_global_struct { + /* input description */ + unsigned long num_samples; /* number of samples. default=2^32-1 */ + int num_channels; /* input number of channels. default=2 */ + int in_samplerate; /* input_samp_rate in Hz. default=44.1 kHz */ + int out_samplerate; /* output_samp_rate. + default: LAME picks best value + at least not used for MP3 decoding: + Remember 44.1 kHz MP3s and AC97 */ + float scale; /* scale input by this amount before encoding + at least not used for MP3 decoding */ + float scale_left; /* scale input of channel 0 (left) by this + amount before encoding */ + float scale_right; /* scale input of channel 1 (right) by this + amount before encoding */ + + /* general control params */ + int analysis; /* collect data for a MP3 frame analyzer? */ + int bWriteVbrTag; /* add Xing VBR tag? */ + int decode_only; /* use lame/mpglib to convert mp3/ogg to wav */ + int ogg; /* encode to Vorbis .ogg file */ + + int quality; /* quality setting 0=best, 9=worst default=5 */ + MPEG_mode mode; /* see enum in lame.h + default = LAME picks best value */ + int mode_fixed; /* ignored */ + int mode_automs; /* use a m/s threshold based on compression + ratio */ + int force_ms; /* force M/S mode. requires mode=1 */ + int free_format; /* use free format? default=0 */ + + /* + * set either brate>0 or compression_ratio>0, LAME will compute + * the value of the variable not set. + * Default is compression_ratio = 11.025 + */ + int brate; /* bitrate */ + float compression_ratio; /* sizeof(wav file)/sizeof(mp3 file) */ + + + /* frame params */ + int copyright; /* mark as copyright. default=0 */ + int original; /* mark as original. default=1 */ + int error_protection; /* use 2 bytes per frame for a CRC + checksum. default=0 */ + Padding_type padding_type; /* PAD_NO = no padding, + PAD_ALL = always pad, + PAD_ADJUST = adjust padding, + default=2 */ + int extension; /* the MP3 'private extension' bit. + Meaningless */ + int strict_ISO; /* enforce ISO spec as much as possible */ + + /* quantization/noise shaping */ + int disable_reservoir; /* use bit reservoir? */ + int experimentalX; + int experimentalY; + int experimentalZ; + int exp_nspsytune; + + double newmsfix; + int preset_expopts; + + /* VBR control */ + vbr_mode VBR; + int VBR_q; + int VBR_mean_bitrate_kbps; + int VBR_min_bitrate_kbps; + int VBR_max_bitrate_kbps; + int VBR_hard_min; /* strictly enforce VBR_min_bitrate + normaly, it will be violated for analog + silence */ + + + /* resampling and filtering */ + int lowpassfreq; /* freq in Hz. 0=lame choses. + -1=no filter */ + int highpassfreq; /* freq in Hz. 0=lame choses. + -1=no filter */ + int lowpasswidth; /* freq width of filter, in Hz + (default=15%) */ + int highpasswidth; /* freq width of filter, in Hz + (default=15%) */ + + + + /* + * psycho acoustics and other arguments which you should not change + * unless you know what you are doing + */ + int ATHonly; /* only use ATH */ + int ATHshort; /* only use ATH for short blocks */ + int noATH; /* disable ATH */ + int ATHtype; /* select ATH formula */ + float ATHlower; /* lower ATH by this many db */ + int athaa_type; /* select ATH auto-adjust scheme */ + int athaa_loudapprox; /* select ATH auto-adjust loudness calc */ + float athaa_sensitivity; /* dB, tune active region of auto-level */ + int cwlimit; /* predictability limit */ + short_block_t short_blocks; +/* int allow_diff_short; allow blocktypes to differ between + channels? */ + int useTemporal; /* use temporal masking effect */ +/* int no_short_blocks; disable short blocks */ + int emphasis; /* Input PCM is emphased PCM (for + instance from one of the rarely + emphased CDs), it is STRONGLY not + recommended to use this, because + psycho does not take it into account, + and last but not least many decoders + don't care about these bits */ + float msfix; /* Naoki's adjustment of Mid/Side maskings */ + + int tune; /* 0 off, 1 on */ + float tune_value_a; /* used to pass values for debugging and stuff */ + + + struct { + void (*msgf) (const char *format, va_list ap); + void (*debugf)(const char *format, va_list ap); + void (*errorf)(const char *format, va_list ap); + } report; + + /************************************************************************/ + /* internal variables, do not set... */ + /* provided because they may be of use to calling application */ + /************************************************************************/ + + int version; /* 0=MPEG-2/2.5 1=MPEG-1 */ + int encoder_delay; + int encoder_padding; /* number of samples of padding appended to input */ + int framesize; + int frameNum; /* number of frames encoded */ + int lame_allocated_gfp; /* is this struct owned by calling + program or lame? */ + + + + /****************************************************************************/ + /* more internal variables, which will not exist after lame_encode_finish() */ + /****************************************************************************/ + lame_internal_flags *internal_flags; + + /* VBR tags. This data is here because VBR header is writen after + * input file is closed and *internal_flags struct is free'd */ + int TotalFrameSize; + //int* pVbrFrames; + int nVbrNumFrames; + int nVbrFrameBufferSize; + + +} ; + +#endif /* LAME_GLOBAL_FLAGS_H */ diff --git a/lib/lame/lameerror.h b/lib/lame/lameerror.h new file mode 100644 index 0000000..a4b9757 --- /dev/null +++ b/lib/lame/lameerror.h @@ -0,0 +1,26 @@ +/* + * A collection of LAME Error Codes + * + * Please use the constants defined here instead of some arbitrary + * values. Currently the values starting at -10 to avoid intersection + * with the -1, -2, -3 and -4 used in the current code. + * + * May be this should be a part of the include/lame.h. + */ + +typedef enum { + LAME_OKAY = 0, + LAME_NOERROR = 0, + LAME_GENERICERROR = -1, + LAME_NOMEM = -10, + LAME_BADBITRATE = -11, + LAME_BADSAMPFREQ = -12, + LAME_INTERNALERROR = -13, + + FRONTEND_READERROR = -80, + FRONTEND_WRITEERROR = -81, + FRONTEND_FILETOOLARGE = -82, + +} lame_errorcodes_t; + +/* end of lameerror.h */ diff --git a/lib/lame/machine.h b/lib/lame/machine.h new file mode 100644 index 0000000..109f291 --- /dev/null +++ b/lib/lame/machine.h @@ -0,0 +1,163 @@ +/* + * Machine dependent defines/includes for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_MACHINE_H +#define LAME_MACHINE_H + +#include + +#ifdef STDC_HEADERS +# include +# include +#else +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr (), *strrchr (); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# define memmove(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#if defined(__riscos__) && defined(FPA10) +# include "ymath.h" +#else +# include +#endif + +#include + +#ifdef HAVE_ERRNO_H +# include +#endif +#ifdef HAVE_FCNTL_H +# include +#endif + +#if defined(macintosh) +# include +# include +#else +# include +# include +#endif + +/* + * 3 different types of pow() functions: + * - table lookup + * - pow() + * - exp() on some machines this is claimed to be faster than pow() + */ + +#define POW20(x) pow20[x] +//#define POW20(x) pow(2.0,((double)(x)-210)*.25) +//#define POW20(x) exp( ((double)(x)-210)*(.25*LOG2) ) + +#define IPOW20(x) ipow20[x] +//#define IPOW20(x) exp( -((double)(x)-210)*.1875*LOG2 ) +//#define IPOW20(x) pow(2.0,-((double)(x)-210)*.1875) + +#define IIPOW20_(x) iipow20_[x] + +/* in case this is used without configure */ +#ifndef inline +# define inline +#endif +/* compatibility */ +#define INLINE inline + +#if defined(_MSC_VER) +# undef inline +# define inline _inline +#elif defined(__SASC) || defined(__GNUC__) || defined(__ICC) || defined(__ECC) +/* if __GNUC__ we always want to inline, not only if the user requests it */ +# undef inline +# define inline __inline +#endif + +#if defined(_MSC_VER) +# pragma warning( disable : 4244 ) +//# pragma warning( disable : 4305 ) +#endif + +/* + * FLOAT for variables which require at least 32 bits + * FLOAT8 for variables which require at least 64 bits + * + * On some machines, 64 bit will be faster than 32 bit. Also, some math + * routines require 64 bit float, so setting FLOAT=float will result in a + * lot of conversions. + */ + +#if ( defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) ) +# define WIN32_LEAN_AND_MEAN +# include +#else +# ifndef FLOAT +typedef float FLOAT; +# ifdef FLT_MAX +# define FLOAT_MAX FLT_MAX +# else +# define FLOAT_MAX 1e99 /* approx */ +# endif +# endif +#endif + +#ifndef FLOAT8 /* NOTE: RH: 7/00: if FLOAT8=float, it breaks resampling and VBR code */ +typedef double FLOAT8; +# ifdef DBL_MAX +# define FLOAT8_MAX DBL_MAX +# else +# define FLOAT8_MAX 1e99 /* approx */ +# endif +#else +# ifdef FLT_MAX +# define FLOAT8_MAX FLT_MAX +# else +# define FLOAT8_MAX 1e99 /* approx */ +# endif +#endif + +/* Various integer types */ + +#if defined _WIN32 && !defined __CYGWIN__ +typedef unsigned char u_char; +#elif defined __DECALPHA__ +// do nothing +#elif defined OS_AMIGAOS +// do nothing +#elif defined __DJGPP__ +typedef unsigned char u_char; +#elif !defined __GNUC__ || defined __STRICT_ANSI__ +typedef unsigned char u_char; +#else +// do nothing +#endif + +/* sample_t must be floating point, at least 32 bits */ +typedef FLOAT sample_t; +typedef sample_t stereo_t [2]; + +#endif + +/* end of machine.h */ diff --git a/lib/lame/newmdct.c b/lib/lame/newmdct.c new file mode 100644 index 0000000..7c5a55a --- /dev/null +++ b/lib/lame/newmdct.c @@ -0,0 +1,790 @@ +/* + * MP3 window subband -> subband filtering -> mdct routine + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +/* + * Special Thanks to Patrick De Smet for your advices. + */ + +/* $Id: newmdct.c,v 1.1 2002/04/28 17:30:23 kramm Exp $ */ + +#include "config_static.h" + +#include "util.h" +#include "l3side.h" +#include "newmdct.h" + +#ifdef WITH_DMALLOC +#include +#endif + +#define SCALE (32768.0/ 2.384e-06) + +#ifndef USE_GOGO_SUBBAND +static const FLOAT8 enwindow[] = +{ + -4.77e-07*0.740951125354959/2.384e-06, 1.03951e-04*0.740951125354959/2.384e-06, 9.53674e-04*0.740951125354959/2.384e-06, 2.841473e-03*0.740951125354959/2.384e-06, + 3.5758972e-02*0.740951125354959/2.384e-06, 3.401756e-03*0.740951125354959/2.384e-06, 9.83715e-04*0.740951125354959/2.384e-06, 9.9182e-05*0.740951125354959/2.384e-06, /* 15*/ + 1.2398e-05*0.740951125354959/2.384e-06, 1.91212e-04*0.740951125354959/2.384e-06, 2.283096e-03*0.740951125354959/2.384e-06,1.6994476e-02*0.740951125354959/2.384e-06, + -1.8756866e-02*0.740951125354959/2.384e-06,-2.630711e-03*0.740951125354959/2.384e-06, -2.47478e-04*0.740951125354959/2.384e-06, -1.4782e-05*0.740951125354959/2.384e-06, + 9.063471690191471e-01, + 1.960342806591213e-01, + + + -4.77e-07*0.773010453362737/2.384e-06, 1.05858e-04*0.773010453362737/2.384e-06, 9.30786e-04*0.773010453362737/2.384e-06, 2.521515e-03*0.773010453362737/2.384e-06, + 3.5694122e-02*0.773010453362737/2.384e-06, 3.643036e-03*0.773010453362737/2.384e-06, 9.91821e-04*0.773010453362737/2.384e-06, 9.6321e-05*0.773010453362737/2.384e-06, /* 14*/ + 1.1444e-05*0.773010453362737/2.384e-06, 1.65462e-04*0.773010453362737/2.384e-06, 2.110004e-03*0.773010453362737/2.384e-06,1.6112804e-02*0.773010453362737/2.384e-06, + -1.9634247e-02*0.773010453362737/2.384e-06,-2.803326e-03*0.773010453362737/2.384e-06, -2.77042e-04*0.773010453362737/2.384e-06, -1.6689e-05*0.773010453362737/2.384e-06, + 8.206787908286602e-01, + 3.901806440322567e-01, + + + -4.77e-07*0.803207531480645/2.384e-06, 1.07288e-04*0.803207531480645/2.384e-06, 9.02653e-04*0.803207531480645/2.384e-06, 2.174854e-03*0.803207531480645/2.384e-06, + 3.5586357e-02*0.803207531480645/2.384e-06, 3.858566e-03*0.803207531480645/2.384e-06, 9.95159e-04*0.803207531480645/2.384e-06, 9.3460e-05*0.803207531480645/2.384e-06, /* 13*/ + 1.0014e-05*0.803207531480645/2.384e-06, 1.40190e-04*0.803207531480645/2.384e-06, 1.937389e-03*0.803207531480645/2.384e-06,1.5233517e-02*0.803207531480645/2.384e-06, + -2.0506859e-02*0.803207531480645/2.384e-06,-2.974033e-03*0.803207531480645/2.384e-06, -3.07560e-04*0.803207531480645/2.384e-06, -1.8120e-05*0.803207531480645/2.384e-06, + 7.416505462720353e-01, + 5.805693545089249e-01, + + + -4.77e-07*0.831469612302545/2.384e-06, 1.08242e-04*0.831469612302545/2.384e-06, 8.68797e-04*0.831469612302545/2.384e-06, 1.800537e-03*0.831469612302545/2.384e-06, + 3.5435200e-02*0.831469612302545/2.384e-06, 4.049301e-03*0.831469612302545/2.384e-06, 9.94205e-04*0.831469612302545/2.384e-06, 9.0599e-05*0.831469612302545/2.384e-06, /* 12*/ + 9.060e-06*0.831469612302545/2.384e-06, 1.16348e-04*0.831469612302545/2.384e-06, 1.766682e-03*0.831469612302545/2.384e-06,1.4358521e-02*0.831469612302545/2.384e-06, + -2.1372318e-02*0.831469612302545/2.384e-06, -3.14188e-03*0.831469612302545/2.384e-06, -3.39031e-04*0.831469612302545/2.384e-06, -1.9550e-05*0.831469612302545/2.384e-06, + 6.681786379192989e-01, + 7.653668647301797e-01, + + + -4.77e-07*0.857728610000272/2.384e-06, 1.08719e-04*0.857728610000272/2.384e-06, 8.29220e-04*0.857728610000272/2.384e-06, 1.399517e-03*0.857728610000272/2.384e-06, + 3.5242081e-02*0.857728610000272/2.384e-06, 4.215240e-03*0.857728610000272/2.384e-06, 9.89437e-04*0.857728610000272/2.384e-06, 8.7261e-05*0.857728610000272/2.384e-06, /* 11*/ + 8.106e-06*0.857728610000272/2.384e-06, 9.3937e-05*0.857728610000272/2.384e-06, 1.597881e-03*0.857728610000272/2.384e-06,1.3489246e-02*0.857728610000272/2.384e-06, + -2.2228718e-02*0.857728610000272/2.384e-06,-3.306866e-03*0.857728610000272/2.384e-06, -3.71456e-04*0.857728610000272/2.384e-06, -2.1458e-05*0.857728610000272/2.384e-06, + 5.993769336819237e-01, + 9.427934736519954e-01, + + + -4.77e-07*0.881921264348355/2.384e-06, 1.08719e-04*0.881921264348355/2.384e-06, 7.8392e-04*0.881921264348355/2.384e-06, 9.71317e-04*0.881921264348355/2.384e-06, + 3.5007000e-02*0.881921264348355/2.384e-06, 4.357815e-03*0.881921264348355/2.384e-06, 9.80854e-04*0.881921264348355/2.384e-06, 8.3923e-05*0.881921264348355/2.384e-06, /* 10*/ + 7.629e-06*0.881921264348355/2.384e-06, 7.2956e-05*0.881921264348355/2.384e-06, 1.432419e-03*0.881921264348355/2.384e-06,1.2627602e-02*0.881921264348355/2.384e-06, + -2.3074150e-02*0.881921264348355/2.384e-06,-3.467083e-03*0.881921264348355/2.384e-06, -4.04358e-04*0.881921264348355/2.384e-06, -2.3365e-05*0.881921264348355/2.384e-06, + 5.345111359507916e-01, + 1.111140466039205e+00, + + + -9.54e-07*0.903989293123443/2.384e-06, 1.08242e-04*0.903989293123443/2.384e-06, 7.31945e-04*0.903989293123443/2.384e-06, 5.15938e-04*0.903989293123443/2.384e-06, + 3.4730434e-02*0.903989293123443/2.384e-06, 4.477024e-03*0.903989293123443/2.384e-06, 9.68933e-04*0.903989293123443/2.384e-06, 8.0585e-05*0.903989293123443/2.384e-06, /* 9*/ + 6.676e-06*0.903989293123443/2.384e-06, 5.2929e-05*0.903989293123443/2.384e-06, 1.269817e-03*0.903989293123443/2.384e-06,1.1775017e-02*0.903989293123443/2.384e-06, + -2.3907185e-02*0.903989293123443/2.384e-06,-3.622532e-03*0.903989293123443/2.384e-06, -4.38213e-04*0.903989293123443/2.384e-06, -2.5272e-05*0.903989293123443/2.384e-06, + 4.729647758913199e-01, + 1.268786568327291e+00, + + + -9.54e-07*0.92387953251128675613/2.384e-06, 1.06812e-04*0.92387953251128675613/2.384e-06, 6.74248e-04*0.92387953251128675613/2.384e-06, 3.3379e-05*0.92387953251128675613/2.384e-06, + 3.4412861e-02*0.92387953251128675613/2.384e-06, 4.573822e-03*0.92387953251128675613/2.384e-06, 9.54151e-04*0.92387953251128675613/2.384e-06, 7.6771e-05*0.92387953251128675613/2.384e-06, + 6.199e-06*0.92387953251128675613/2.384e-06, 3.4332e-05*0.92387953251128675613/2.384e-06, 1.111031e-03*0.92387953251128675613/2.384e-06,1.0933399e-02*0.92387953251128675613/2.384e-06, + -2.4725437e-02*0.92387953251128675613/2.384e-06,-3.771782e-03*0.92387953251128675613/2.384e-06, -4.72546e-04*0.92387953251128675613/2.384e-06, -2.7657e-05*0.92387953251128675613/2.384e-06, + 4.1421356237309504879e-01, /* tan(PI/8) */ + 1.414213562373095e+00, + + + -9.54e-07*0.941544065183021/2.384e-06, 1.05381e-04*0.941544065183021/2.384e-06, 6.10352e-04*0.941544065183021/2.384e-06, -4.75883e-04*0.941544065183021/2.384e-06, + 3.4055710e-02*0.941544065183021/2.384e-06, 4.649162e-03*0.941544065183021/2.384e-06, 9.35555e-04*0.941544065183021/2.384e-06, 7.3433e-05*0.941544065183021/2.384e-06, /* 7*/ + 5.245e-06*0.941544065183021/2.384e-06, 1.7166e-05*0.941544065183021/2.384e-06, 9.56535e-04*0.941544065183021/2.384e-06,1.0103703e-02*0.941544065183021/2.384e-06, + -2.5527000e-02*0.941544065183021/2.384e-06,-3.914356e-03*0.941544065183021/2.384e-06, -5.07355e-04*0.941544065183021/2.384e-06, -3.0041e-05*0.941544065183021/2.384e-06, + 3.578057213145241e-01, + 1.546020906725474e+00, + + + -9.54e-07*0.956940335732209/2.384e-06, 1.02520e-04*0.956940335732209/2.384e-06, 5.39303e-04*0.956940335732209/2.384e-06,-1.011848e-03*0.956940335732209/2.384e-06, + 3.3659935e-02*0.956940335732209/2.384e-06, 4.703045e-03*0.956940335732209/2.384e-06, 9.15051e-04*0.956940335732209/2.384e-06, 7.0095e-05*0.956940335732209/2.384e-06, /* 6*/ + 4.768e-06*0.956940335732209/2.384e-06, 9.54e-07*0.956940335732209/2.384e-06, 8.06808e-04*0.956940335732209/2.384e-06, 9.287834e-03*0.956940335732209/2.384e-06, + -2.6310921e-02*0.956940335732209/2.384e-06,-4.048824e-03*0.956940335732209/2.384e-06, -5.42164e-04*0.956940335732209/2.384e-06, -3.2425e-05*0.956940335732209/2.384e-06, + 3.033466836073424e-01, + 1.662939224605090e+00, + + + -1.431e-06*0.970031253194544/2.384e-06, 9.9182e-05*0.970031253194544/2.384e-06, 4.62532e-04*0.970031253194544/2.384e-06,-1.573563e-03*0.970031253194544/2.384e-06, + 3.3225536e-02*0.970031253194544/2.384e-06, 4.737377e-03*0.970031253194544/2.384e-06, 8.91685e-04*0.970031253194544/2.384e-06, 6.6280e-05*0.970031253194544/2.384e-06, /* 5*/ + 4.292e-06*0.970031253194544/2.384e-06, -1.3828e-05*0.970031253194544/2.384e-06, 6.61850e-04*0.970031253194544/2.384e-06, 8.487225e-03*0.970031253194544/2.384e-06, + -2.7073860e-02*0.970031253194544/2.384e-06,-4.174709e-03*0.970031253194544/2.384e-06, -5.76973e-04*0.970031253194544/2.384e-06, -3.4809e-05*0.970031253194544/2.384e-06, + 2.504869601913055e-01, + 1.763842528696710e+00, + + + -1.431e-06*0.98078528040323/2.384e-06, 9.5367e-05*0.98078528040323/2.384e-06, 3.78609e-04*0.98078528040323/2.384e-06,-2.161503e-03*0.98078528040323/2.384e-06, + 3.2754898e-02*0.98078528040323/2.384e-06, 4.752159e-03*0.98078528040323/2.384e-06, 8.66413e-04*0.98078528040323/2.384e-06, 6.2943e-05*0.98078528040323/2.384e-06, /* 4*/ + 3.815e-06*0.98078528040323/2.384e-06, -2.718e-05*0.98078528040323/2.384e-06, 5.22137e-04*0.98078528040323/2.384e-06, 7.703304e-03*0.98078528040323/2.384e-06, + -2.7815342e-02*0.98078528040323/2.384e-06,-4.290581e-03*0.98078528040323/2.384e-06, -6.11782e-04*0.98078528040323/2.384e-06, -3.7670e-05*0.98078528040323/2.384e-06, + 1.989123673796580e-01, + 1.847759065022573e+00, + + + -1.907e-06*0.989176509964781/2.384e-06, 9.0122e-05*0.989176509964781/2.384e-06, 2.88486e-04*0.989176509964781/2.384e-06,-2.774239e-03*0.989176509964781/2.384e-06, + 3.2248020e-02*0.989176509964781/2.384e-06, 4.748821e-03*0.989176509964781/2.384e-06, 8.38757e-04*0.989176509964781/2.384e-06, 5.9605e-05*0.989176509964781/2.384e-06, /* 3*/ + 3.338e-06*0.989176509964781/2.384e-06, -3.9577e-05*0.989176509964781/2.384e-06, 3.88145e-04*0.989176509964781/2.384e-06, 6.937027e-03*0.989176509964781/2.384e-06, + -2.8532982e-02*0.989176509964781/2.384e-06,-4.395962e-03*0.989176509964781/2.384e-06, -6.46591e-04*0.989176509964781/2.384e-06, -4.0531e-05*0.989176509964781/2.384e-06, + 1.483359875383474e-01, + 1.913880671464418e+00, + + + -1.907e-06*0.995184726672197/2.384e-06, 8.4400e-05*0.995184726672197/2.384e-06, 1.91689e-04*0.995184726672197/2.384e-06,-3.411293e-03*0.995184726672197/2.384e-06, + 3.1706810e-02*0.995184726672197/2.384e-06, 4.728317e-03*0.995184726672197/2.384e-06, 8.09669e-04*0.995184726672197/2.384e-06, 5.579e-05*0.995184726672197/2.384e-06, + 3.338e-06*0.995184726672197/2.384e-06, -5.0545e-05*0.995184726672197/2.384e-06, 2.59876e-04*0.995184726672197/2.384e-06, 6.189346e-03*0.995184726672197/2.384e-06, + -2.9224873e-02*0.995184726672197/2.384e-06,-4.489899e-03*0.995184726672197/2.384e-06, -6.80923e-04*0.995184726672197/2.384e-06, -4.3392e-05*0.995184726672197/2.384e-06, + 9.849140335716425e-02, + 1.961570560806461e+00, + + + -2.384e-06*0.998795456205172/2.384e-06, 7.7724e-05*0.998795456205172/2.384e-06, 8.8215e-05*0.998795456205172/2.384e-06,-4.072189e-03*0.998795456205172/2.384e-06, + 3.1132698e-02*0.998795456205172/2.384e-06, 4.691124e-03*0.998795456205172/2.384e-06, 7.79152e-04*0.998795456205172/2.384e-06, 5.2929e-05*0.998795456205172/2.384e-06, + 2.861e-06*0.998795456205172/2.384e-06, -6.0558e-05*0.998795456205172/2.384e-06, 1.37329e-04*0.998795456205172/2.384e-06, 5.462170e-03*0.998795456205172/2.384e-06, + -2.9890060e-02*0.998795456205172/2.384e-06,-4.570484e-03*0.998795456205172/2.384e-06, -7.14302e-04*0.998795456205172/2.384e-06, -4.6253e-05*0.998795456205172/2.384e-06, + 4.912684976946725e-02, + 1.990369453344394e+00, + + + 3.5780907e-02 * SQRT2*0.5/2.384e-06,1.7876148e-02 * SQRT2*0.5/2.384e-06, 3.134727e-03 * SQRT2*0.5/2.384e-06, 2.457142e-03 * SQRT2*0.5/2.384e-06, + 9.71317e-04 * SQRT2*0.5/2.384e-06, 2.18868e-04 * SQRT2*0.5/2.384e-06, 1.01566e-04 * SQRT2*0.5/2.384e-06, 1.3828e-05 * SQRT2*0.5/2.384e-06, + + 3.0526638e-02/2.384e-06, 4.638195e-03/2.384e-06, 7.47204e-04/2.384e-06, 4.9591e-05/2.384e-06, + 4.756451e-03/2.384e-06, 2.1458e-05/2.384e-06, -6.9618e-05/2.384e-06,/* 2.384e-06/2.384e-06*/ +}; +#endif + + +#define NS 12 +#define NL 36 + +static const FLOAT8 win[4][NL] = { + { + 2.382191739347913e-13, + 6.423305872147834e-13, + 9.400849094049688e-13, + 1.122435026096556e-12, + 1.183840321267481e-12, + 1.122435026096556e-12, + 9.400849094049690e-13, + 6.423305872147839e-13, + 2.382191739347918e-13, + + 5.456116108943412e-12, + 4.878985199565852e-12, + 4.240448995017367e-12, + 3.559909094758252e-12, + 2.858043359288075e-12, + 2.156177623817898e-12, + 1.475637723558783e-12, + 8.371015190102974e-13, + 2.599706096327376e-13, + + -5.456116108943412e-12, + -4.878985199565852e-12, + -4.240448995017367e-12, + -3.559909094758252e-12, + -2.858043359288076e-12, + -2.156177623817898e-12, + -1.475637723558783e-12, + -8.371015190102975e-13, + -2.599706096327376e-13, + + -2.382191739347923e-13, + -6.423305872147843e-13, + -9.400849094049696e-13, + -1.122435026096556e-12, + -1.183840321267481e-12, + -1.122435026096556e-12, + -9.400849094049694e-13, + -6.423305872147840e-13, + -2.382191739347918e-13, + }, + { + 2.382191739347913e-13, + 6.423305872147834e-13, + 9.400849094049688e-13, + 1.122435026096556e-12, + 1.183840321267481e-12, + 1.122435026096556e-12, + 9.400849094049688e-13, + 6.423305872147841e-13, + 2.382191739347918e-13, + + 5.456116108943413e-12, + 4.878985199565852e-12, + 4.240448995017367e-12, + 3.559909094758253e-12, + 2.858043359288075e-12, + 2.156177623817898e-12, + 1.475637723558782e-12, + 8.371015190102975e-13, + 2.599706096327376e-13, + + -5.461314069809755e-12, + -4.921085770524055e-12, + -4.343405037091838e-12, + -3.732668368707687e-12, + -3.093523840190885e-12, + -2.430835727329465e-12, + -1.734679010007751e-12, + -9.748253656609281e-13, + -2.797435120168326e-13, + + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + -2.283748241799531e-13, + -4.037858874020686e-13, + -2.146547464825323e-13, + }, + { + 1.316524975873958e-01, /* win[SHORT_TYPE] */ + 4.142135623730950e-01, + 7.673269879789602e-01, + + 1.091308501069271e+00, /* tantab_l */ + 1.303225372841206e+00, + 1.569685577117490e+00, + 1.920982126971166e+00, + 2.414213562373094e+00, + 3.171594802363212e+00, + 4.510708503662055e+00, + 7.595754112725146e+00, + 2.290376554843115e+01, + + 0.98480775301220802032, /* cx */ + 0.64278760968653936292, + 0.34202014332566882393, + 0.93969262078590842791, + -0.17364817766693030343, + -0.76604444311897790243, + 0.86602540378443870761, + 0.500000000000000e+00, + + -5.144957554275265e-01, /* ca */ + -4.717319685649723e-01, + -3.133774542039019e-01, + -1.819131996109812e-01, + -9.457419252642064e-02, + -4.096558288530405e-02, + -1.419856857247115e-02, + -3.699974673760037e-03, + + 8.574929257125442e-01, /* cs */ + 8.817419973177052e-01, + 9.496286491027329e-01, + 9.833145924917901e-01, + 9.955178160675857e-01, + 9.991605581781475e-01, + 9.998991952444470e-01, + 9.999931550702802e-01, + }, + { + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 0.000000000000000e+00, + 2.283748241799531e-13, + 4.037858874020686e-13, + 2.146547464825323e-13, + + 5.461314069809755e-12, + 4.921085770524055e-12, + 4.343405037091838e-12, + 3.732668368707687e-12, + 3.093523840190885e-12, + 2.430835727329466e-12, + 1.734679010007751e-12, + 9.748253656609281e-13, + 2.797435120168326e-13, + + -5.456116108943413e-12, + -4.878985199565852e-12, + -4.240448995017367e-12, + -3.559909094758253e-12, + -2.858043359288075e-12, + -2.156177623817898e-12, + -1.475637723558782e-12, + -8.371015190102975e-13, + -2.599706096327376e-13, + + -2.382191739347913e-13, + -6.423305872147834e-13, + -9.400849094049688e-13, + -1.122435026096556e-12, + -1.183840321267481e-12, + -1.122435026096556e-12, + -9.400849094049688e-13, + -6.423305872147841e-13, + -2.382191739347918e-13, + } +}; + +#define tantab_l (win[SHORT_TYPE]+3) +#define cx (win[SHORT_TYPE]+12) +#define ca (win[SHORT_TYPE]+20) +#define cs (win[SHORT_TYPE]+28) + +/************************************************************************ +* +* window_subband() +* +* PURPOSE: Overlapping window on PCM samples +* +* SEMANTICS: +* 32 16-bit pcm samples are scaled to fractional 2's complement and +* concatenated to the end of the window buffer #x#. The updated window +* buffer #x# is then windowed by the analysis window #c# to produce the +* windowed sample #z# +* +************************************************************************/ + +/* + * new IDCT routine written by Takehiro TOMINAGA + */ +static const int order[] = { + 0, 1,16,17, 8, 9,24,25, 4, 5,20,21,12,13,28,29, + 2, 3,18,19,10,11,26,27, 6, 7,22,23,14,15,30,31 +}; + + +/* returns sum_j=0^31 a[j]*cos(PI*j*(k+1/2)/32), 0<=k<32 */ +INLINE static void +window_subband(const sample_t *x1, FLOAT8 a[SBLIMIT]) +{ + int i; + FLOAT8 const *wp = enwindow+10; + + const sample_t *x2 = &x1[238-14-286]; + + for (i = -15; i < 0; i++) { + FLOAT8 w, s, t; + + w = wp[-10]; s = x2[-224] * w; t = x1[ 224] * w; + w = wp[-9]; s += x2[-160] * w; t += x1[ 160] * w; + w = wp[-8]; s += x2[- 96] * w; t += x1[ 96] * w; + w = wp[-7]; s += x2[- 32] * w; t += x1[ 32] * w; + w = wp[-6]; s += x2[ 32] * w; t += x1[- 32] * w; + w = wp[-5]; s += x2[ 96] * w; t += x1[- 96] * w; + w = wp[-4]; s += x2[ 160] * w; t += x1[-160] * w; + w = wp[-3]; s += x2[ 224] * w; t += x1[-224] * w; + + w = wp[-2]; s += x1[-256] * w; t -= x2[ 256] * w; + w = wp[-1]; s += x1[-192] * w; t -= x2[ 192] * w; + w = wp[ 0]; s += x1[-128] * w; t -= x2[ 128] * w; + w = wp[ 1]; s += x1[- 64] * w; t -= x2[ 64] * w; + w = wp[ 2]; s += x1[ 0] * w; t -= x2[ 0] * w; + w = wp[ 3]; s += x1[ 64] * w; t -= x2[- 64] * w; + w = wp[ 4]; s += x1[ 128] * w; t -= x2[-128] * w; + w = wp[ 5]; s += x1[ 192] * w; t -= x2[-192] * w; + + /* + * this multiplyer could be removed, but it needs more 256 FLOAT data. + * thinking about the data cache performance, I think we should not + * use such a huge table. tt 2000/Oct/25 + */ + s *= wp[6]; + w = t - s; + a[30+i*2] = t + s; + a[31+i*2] = wp[7] * w; + wp += 18; + x1--; + x2++; + } + { + FLOAT8 s,t,u,v; + t = x1[- 16] * wp[-10]; s = x1[ -32] * wp[-2]; + t += (x1[- 48] - x1[ 16]) * wp[-9]; s += x1[ -96] * wp[-1]; + t += (x1[- 80] + x1[ 48]) * wp[-8]; s += x1[-160] * wp[ 0]; + t += (x1[-112] - x1[ 80]) * wp[-7]; s += x1[-224] * wp[ 1]; + t += (x1[-144] + x1[112]) * wp[-6]; s -= x1[ 32] * wp[ 2]; + t += (x1[-176] - x1[144]) * wp[-5]; s -= x1[ 96] * wp[ 3]; + t += (x1[-208] + x1[176]) * wp[-4]; s -= x1[ 160] * wp[ 4]; + t += (x1[-240] - x1[208]) * wp[-3]; s -= x1[ 224]; + + u = s - t; + v = s + t; + + t = a[14]; + s = a[15] - t; + + a[31] = v + t; // A0 + a[30] = u + s; // A1 + a[15] = u - s; // A2 + a[14] = v - t; // A3 + } +{ + FLOAT8 xr; + xr = a[28] - a[ 0]; a[ 0] += a[28]; a[28] = xr * wp[-2*18+7]; + xr = a[29] - a[ 1]; a[ 1] += a[29]; a[29] = xr * wp[-2*18+7]; + + xr = a[26] - a[ 2]; a[ 2] += a[26]; a[26] = xr * wp[-4*18+7]; + xr = a[27] - a[ 3]; a[ 3] += a[27]; a[27] = xr * wp[-4*18+7]; + + xr = a[24] - a[ 4]; a[ 4] += a[24]; a[24] = xr * wp[-6*18+7]; + xr = a[25] - a[ 5]; a[ 5] += a[25]; a[25] = xr * wp[-6*18+7]; + + xr = a[22] - a[ 6]; a[ 6] += a[22]; a[22] = xr * SQRT2; + xr = a[23] - a[ 7]; a[ 7] += a[23]; a[23] = xr * SQRT2 - a[ 7]; + a[ 7] -= a[ 6]; + a[22] -= a[ 7]; + a[23] -= a[22]; + + xr = a[ 6]; a[ 6] = a[31] - xr; a[31] = a[31] + xr; + xr = a[ 7]; a[ 7] = a[30] - xr; a[30] = a[30] + xr; + xr = a[22]; a[22] = a[15] - xr; a[15] = a[15] + xr; + xr = a[23]; a[23] = a[14] - xr; a[14] = a[14] + xr; + + xr = a[20] - a[ 8]; a[ 8] += a[20]; a[20] = xr * wp[-10*18+7]; + xr = a[21] - a[ 9]; a[ 9] += a[21]; a[21] = xr * wp[-10*18+7]; + + xr = a[18] - a[10]; a[10] += a[18]; a[18] = xr * wp[-12*18+7]; + xr = a[19] - a[11]; a[11] += a[19]; a[19] = xr * wp[-12*18+7]; + + xr = a[16] - a[12]; a[12] += a[16]; a[16] = xr * wp[-14*18+7]; + xr = a[17] - a[13]; a[13] += a[17]; a[17] = xr * wp[-14*18+7]; + + xr = -a[20] + a[24]; a[20] += a[24]; a[24] = xr * wp[-12*18+7]; + xr = -a[21] + a[25]; a[21] += a[25]; a[25] = xr * wp[-12*18+7]; + + xr = a[ 4] - a[ 8]; a[ 4] += a[ 8]; a[ 8] = xr * wp[-12*18+7]; + xr = a[ 5] - a[ 9]; a[ 5] += a[ 9]; a[ 9] = xr * wp[-12*18+7]; + + xr = a[ 0] - a[12]; a[ 0] += a[12]; a[12] = xr * wp[-4*18+7]; + xr = a[ 1] - a[13]; a[ 1] += a[13]; a[13] = xr * wp[-4*18+7]; + xr = a[16] - a[28]; a[16] += a[28]; a[28] = xr * wp[-4*18+7]; + xr = -a[17] + a[29]; a[17] += a[29]; a[29] = xr * wp[-4*18+7]; + + xr = SQRT2 * (a[ 2] - a[10]); a[ 2] += a[10]; a[10] = xr; + xr = SQRT2 * (a[ 3] - a[11]); a[ 3] += a[11]; a[11] = xr; + xr = SQRT2 * (-a[18] + a[26]); a[18] += a[26]; a[26] = xr - a[18]; + xr = SQRT2 * (-a[19] + a[27]); a[19] += a[27]; a[27] = xr - a[19]; + + xr = a[ 2]; a[19] -= a[ 3]; a[ 3] -= xr; a[ 2] = a[31] - xr; a[31] += xr; + xr = a[ 3]; a[11] -= a[19]; a[18] -= xr; a[ 3] = a[30] - xr; a[30] += xr; + xr = a[18]; a[27] -= a[11]; a[19] -= xr; a[18] = a[15] - xr; a[15] += xr; + + xr = a[19]; a[10] -= xr; a[19] = a[14] - xr; a[14] += xr; + xr = a[10]; a[11] -= xr; a[10] = a[23] - xr; a[23] += xr; + xr = a[11]; a[26] -= xr; a[11] = a[22] - xr; a[22] += xr; + xr = a[26]; a[27] -= xr; a[26] = a[ 7] - xr; a[ 7] += xr; + + xr = a[27]; a[27] = a[ 6] - xr; a[ 6] += xr; + + xr = SQRT2 * (a[ 0] - a[ 4]); a[ 0] += a[ 4]; a[ 4] = xr; + xr = SQRT2 * (a[ 1] - a[ 5]); a[ 1] += a[ 5]; a[ 5] = xr; + xr = SQRT2 * (a[16] - a[20]); a[16] += a[20]; a[20] = xr; + xr = SQRT2 * (a[17] - a[21]); a[17] += a[21]; a[21] = xr; + + xr = -SQRT2 * (a[ 8] - a[12]); a[ 8] += a[12]; a[12] = xr - a[ 8]; + xr = -SQRT2 * (a[ 9] - a[13]); a[ 9] += a[13]; a[13] = xr - a[ 9]; + xr = -SQRT2 * (a[25] - a[29]); a[25] += a[29]; a[29] = xr - a[25]; + xr = -SQRT2 * (a[24] + a[28]); a[24] -= a[28]; a[28] = xr - a[24]; + + xr = a[24] - a[16]; a[24] = xr; + xr = a[20] - xr; a[20] = xr; + xr = a[28] - xr; a[28] = xr; + + xr = a[25] - a[17]; a[25] = xr; + xr = a[21] - xr; a[21] = xr; + xr = a[29] - xr; a[29] = xr; + + xr = a[17] - a[ 1]; a[17] = xr; + xr = a[ 9] - xr; a[ 9] = xr; + xr = a[25] - xr; a[25] = xr; + xr = a[ 5] - xr; a[ 5] = xr; + xr = a[21] - xr; a[21] = xr; + xr = a[13] - xr; a[13] = xr; + xr = a[29] - xr; a[29] = xr; + + xr = a[ 1] - a[ 0]; a[ 1] = xr; + xr = a[16] - xr; a[16] = xr; + xr = a[17] - xr; a[17] = xr; + xr = a[ 8] - xr; a[ 8] = xr; + xr = a[ 9] - xr; a[ 9] = xr; + xr = a[24] - xr; a[24] = xr; + xr = a[25] - xr; a[25] = xr; + xr = a[ 4] - xr; a[ 4] = xr; + xr = a[ 5] - xr; a[ 5] = xr; + xr = a[20] - xr; a[20] = xr; + xr = a[21] - xr; a[21] = xr; + xr = a[12] - xr; a[12] = xr; + xr = a[13] - xr; a[13] = xr; + xr = a[28] - xr; a[28] = xr; + xr = a[29] - xr; a[29] = xr; + + xr = a[ 0]; a[ 0] += a[31]; a[31] -= xr; + xr = a[ 1]; a[ 1] += a[30]; a[30] -= xr; + xr = a[16]; a[16] += a[15]; a[15] -= xr; + xr = a[17]; a[17] += a[14]; a[14] -= xr; + xr = a[ 8]; a[ 8] += a[23]; a[23] -= xr; + xr = a[ 9]; a[ 9] += a[22]; a[22] -= xr; + xr = a[24]; a[24] += a[ 7]; a[ 7] -= xr; + xr = a[25]; a[25] += a[ 6]; a[ 6] -= xr; + xr = a[ 4]; a[ 4] += a[27]; a[27] -= xr; + xr = a[ 5]; a[ 5] += a[26]; a[26] -= xr; + xr = a[20]; a[20] += a[11]; a[11] -= xr; + xr = a[21]; a[21] += a[10]; a[10] -= xr; + xr = a[12]; a[12] += a[19]; a[19] -= xr; + xr = a[13]; a[13] += a[18]; a[18] -= xr; + xr = a[28]; a[28] += a[ 3]; a[ 3] -= xr; + xr = a[29]; a[29] += a[ 2]; a[ 2] -= xr; +} + +} + + +/*-------------------------------------------------------------------*/ +/* */ +/* Function: Calculation of the MDCT */ +/* In the case of long blocks (type 0,1,3) there are */ +/* 36 coefficents in the time domain and 18 in the frequency */ +/* domain. */ +/* In the case of short blocks (type 2) there are 3 */ +/* transformations with short length. This leads to 12 coefficents */ +/* in the time and 6 in the frequency domain. In this case the */ +/* results are stored side by side in the vector out[]. */ +/* */ +/* New layer3 */ +/* */ +/*-------------------------------------------------------------------*/ + +inline static void mdct_short(FLOAT8 *inout) +{ + int l; + for ( l = 0; l < 3; l++ ) { + FLOAT8 tc0,tc1,tc2,ts0,ts1,ts2; + + ts0 = inout[2*3] * win[SHORT_TYPE][0] - inout[5*3]; + tc0 = inout[0*3] * win[SHORT_TYPE][2] - inout[3*3]; + tc1 = ts0 + tc0; + tc2 = ts0 - tc0; + + ts0 = inout[5*3] * win[SHORT_TYPE][0] + inout[2*3]; + tc0 = inout[3*3] * win[SHORT_TYPE][2] + inout[0*3]; + ts1 = ts0 + tc0; + ts2 = -ts0 + tc0; + + tc0 = (inout[1*3] * win[SHORT_TYPE][1] - inout[4*3]) * 2.069978111953089e-11; /* tritab_s[1] */ + ts0 = (inout[4*3] * win[SHORT_TYPE][1] + inout[1*3]) * 2.069978111953089e-11; /* tritab_s[1] */ + + inout[3*0] = tc1 * 1.907525191737280e-11 /* tritab_s[2] */ + tc0; + inout[3*5] = -ts1 * 1.907525191737280e-11 /* tritab_s[0] */ + ts0; + + tc2 = tc2 * 0.86602540378443870761 * 1.907525191737281e-11 /* tritab_s[2] */; + ts1 = ts1 * 0.5 * 1.907525191737281e-11 + ts0; + inout[3*1] = tc2-ts1; + inout[3*2] = tc2+ts1; + + tc1 = tc1 * 0.5 * 1.907525191737281e-11 - tc0; + ts2 = ts2 * 0.86602540378443870761 * 1.907525191737281e-11 /* tritab_s[0] */; + inout[3*3] = tc1+ts2; + inout[3*4] = tc1-ts2; + + inout++; + } +} + +inline static void mdct_long(FLOAT8 *out, FLOAT8 *in) +{ + FLOAT8 ct,st; + { + FLOAT8 tc1, tc2, tc3, tc4, ts5, ts6, ts7, ts8; + // 1,2, 5,6, 9,10, 13,14, 17 + tc1 = in[17]-in[ 9]; + tc3 = in[15]-in[11]; + tc4 = in[14]-in[12]; + ts5 = in[ 0]+in[ 8]; + ts6 = in[ 1]+in[ 7]; + ts7 = in[ 2]+in[ 6]; + ts8 = in[ 3]+in[ 5]; + + out[17] = (ts5+ts7-ts8)-(ts6-in[4]); + st = (ts5+ts7-ts8)*cx[7]+(ts6-in[4]); + ct = (tc1-tc3-tc4)*cx[6]; + out[5] = ct+st; + out[6] = ct-st; + + tc2 = (in[16]-in[10])*cx[6]; + ts6 = ts6*cx[7] + in[4]; + ct = tc1*cx[0] + tc2 + tc3*cx[1] + tc4*cx[2]; + st = -ts5*cx[4] + ts6 - ts7*cx[5] + ts8*cx[3]; + out[1] = ct+st; + out[2] = ct-st; + + ct = tc1*cx[1] - tc2 - tc3*cx[2] + tc4*cx[0]; + st = -ts5*cx[5] + ts6 - ts7*cx[3] + ts8*cx[4]; + out[ 9] = ct+st; + out[10] = ct-st; + + ct = tc1*cx[2] - tc2 + tc3*cx[0] - tc4*cx[1]; + st = ts5*cx[3] - ts6 + ts7*cx[4] - ts8*cx[5]; + out[13] = ct+st; + out[14] = ct-st; + } + { + FLOAT8 ts1, ts2, ts3, ts4, tc5, tc6, tc7, tc8; + + ts1 = in[ 8]-in[ 0]; + ts3 = in[ 6]-in[ 2]; + ts4 = in[ 5]-in[ 3]; + tc5 = in[17]+in[ 9]; + tc6 = in[16]+in[10]; + tc7 = in[15]+in[11]; + tc8 = in[14]+in[12]; + + out[0] = (tc5+tc7+tc8)+(tc6+in[13]); + ct = (tc5+tc7+tc8)*cx[7]-(tc6+in[13]); + st = (ts1-ts3+ts4)*cx[6]; + out[11] = ct+st; + out[12] = ct-st; + + ts2 = (in[7]-in[1])*cx[6]; + tc6 = in[13] - tc6*cx[7]; + ct = tc5*cx[3] - tc6 + tc7*cx[4] + tc8*cx[5]; + st = ts1*cx[2] + ts2 + ts3*cx[0] + ts4*cx[1]; + out[3] = ct+st; + out[4] = ct-st; + + ct = -tc5*cx[5] + tc6 - tc7*cx[3] - tc8*cx[4]; + st = ts1*cx[1] + ts2 - ts3*cx[2] - ts4*cx[0]; + out[7] = ct+st; + out[8] = ct-st; + + ct = -tc5*cx[4] + tc6 - tc7*cx[5] - tc8*cx[3]; + st = ts1*cx[0] - ts2 + ts3*cx[1] - ts4*cx[2]; + out[15] = ct+st; + out[16] = ct-st; + } +} + + +void mdct_sub48( lame_internal_flags *gfc, const sample_t *w0, const sample_t *w1, + FLOAT8 mdct_freq[2][2][576] ) +{ + int gr, k, ch; + const sample_t *wk; + + wk = w0 + 286; + /* thinking cache performance, ch->gr loop is better than gr->ch loop */ + for (ch = 0; ch < gfc->channels_out; ch++) { + for (gr = 0; gr < gfc->mode_gr; gr++) { + int band; + FLOAT8 *mdct_enc = &mdct_freq[gr][ch][0]; + gr_info *gi = &(gfc->l3_side.gr[gr].ch[ch].tt); + FLOAT8 *samp = gfc->sb_sample[ch][1 - gr][0]; + + for (k = 0; k < 18 / 2; k++) { + window_subband(wk, samp); + window_subband(wk + 32, samp + 32); + samp += 64; + wk += 64; + /* + * Compensate for inversion in the analysis filter + */ + for (band = 1; band < 32; band+=2) { + samp[band-32] *= -1; + } + } + + + /* apply filters on the polyphase filterbank outputs */ + /* bands <= gfc->highpass_band will be zeroed out below */ + /* bands >= gfc->lowpass_band will be zeroed out below */ + if (gfc->filter_type==0) { + for (band=gfc->highpass_start_band; band <= gfc->highpass_end_band; band++) { + for (k=0; k<18; k++) + gfc->sb_sample[ch][1-gr][k][order[band]]*=gfc->amp_highpass[band]; + } + for (band=gfc->lowpass_start_band; band <= gfc->lowpass_end_band; band++) { + for (k=0; k<18; k++) + gfc->sb_sample[ch][1-gr][k][order[band]]*=gfc->amp_lowpass[band]; + } + } + + + + /* + * Perform imdct of 18 previous subband samples + * + 18 current subband samples + */ + for (band = 0; band < 32; band++, mdct_enc += 18) { + int type = gi->block_type; + FLOAT8 *band0, *band1; + band0 = gfc->sb_sample[ch][ gr][0] + order[band]; + band1 = gfc->sb_sample[ch][1-gr][0] + order[band]; + if (gi->mixed_block_flag && band < 2) + type = 0; + if (band >= gfc->lowpass_band || band <= gfc->highpass_band) { + memset((char *)mdct_enc,0,18*sizeof(FLOAT8)); + } else { + if (type == SHORT_TYPE) { + for (k = -NS/4; k < 0; k++) { + FLOAT8 w = win[SHORT_TYPE][k+3]; + mdct_enc[k*3+ 9] = band0[( 9+k)*32] * w - band0[( 8-k)*32]; + mdct_enc[k*3+18] = band0[(14-k)*32] * w + band0[(15+k)*32]; + mdct_enc[k*3+10] = band0[(15+k)*32] * w - band0[(14-k)*32]; + mdct_enc[k*3+19] = band1[( 2-k)*32] * w + band1[( 3+k)*32]; + mdct_enc[k*3+11] = band1[( 3+k)*32] * w - band1[( 2-k)*32]; + mdct_enc[k*3+20] = band1[( 8-k)*32] * w + band1[( 9+k)*32]; + } + mdct_short(mdct_enc); + } else { + FLOAT8 work[18]; + for (k = -NL/4; k < 0; k++) { + FLOAT8 a, b; + a = win[type][k+27] * band1[(k+9)*32] + + win[type][k+36] * band1[(8-k)*32]; + b = win[type][k+ 9] * band0[(k+9)*32] + - win[type][k+18] * band0[(8-k)*32]; + work[k+ 9] = a - b*tantab_l[k+9]; + work[k+18] = a*tantab_l[k+9] + b; + } + + mdct_long(mdct_enc, work); + } + } + /* + * Perform aliasing reduction butterfly + */ + if (type != SHORT_TYPE) { + if (band == 0) + continue; + for (k = 7; k >= 0; --k) { + FLOAT8 bu,bd; + bu = mdct_enc[k] * ca[k] + mdct_enc[-1-k] * cs[k]; + bd = mdct_enc[k] * cs[k] - mdct_enc[-1-k] * ca[k]; + + mdct_enc[-1-k] = bu; + mdct_enc[k] = bd; + } + } + } + } + wk = w1 + 286; + if (gfc->mode_gr == 1) { + memcpy(gfc->sb_sample[ch][0], gfc->sb_sample[ch][1], 576 * sizeof(FLOAT8)); + } + } +} diff --git a/lib/lame/newmdct.h b/lib/lame/newmdct.h new file mode 100644 index 0000000..14344f7 --- /dev/null +++ b/lib/lame/newmdct.h @@ -0,0 +1,28 @@ +/* + * New Modified DCT include file + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_NEWMDCT_H +#define LAME_NEWMDCT_H + +void mdct_sub48(lame_internal_flags *gfc,const sample_t *w0, const sample_t *w1, + FLOAT8 mdct_freq[2][2][576]); + +#endif /* LAME_NEWMDCT_H */ diff --git a/lib/lame/psymodel.c b/lib/lame/psymodel.c new file mode 100644 index 0000000..b4c770e --- /dev/null +++ b/lib/lame/psymodel.c @@ -0,0 +1,2538 @@ +/* + * psymodel.c + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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: psymodel.c,v 1.1 2002/04/28 17:30:23 kramm Exp $ */ + + +/* +PSYCHO ACOUSTICS + + +This routine computes the psycho acoustics, delayed by +one granule. + +Input: buffer of PCM data (1024 samples). + +This window should be centered over the 576 sample granule window. +The routine will compute the psycho acoustics for +this granule, but return the psycho acoustics computed +for the *previous* granule. This is because the block +type of the previous granule can only be determined +after we have computed the psycho acoustics for the following +granule. + +Output: maskings and energies for each scalefactor band. +block type, PE, and some correlation measures. +The PE is used by CBR modes to determine if extra bits +from the bit reservoir should be used. The correlation +measures are used to determine mid/side or regular stereo. + + +Notation: + +barks: a non-linear frequency scale. Mapping from frequency to + barks is given by freq2bark() + +scalefactor bands: The spectrum (frequencies) are broken into + SBMAX "scalefactor bands". Thes bands + are determined by the MPEG ISO spec. In + the noise shaping/quantization code, we allocate + bits among the partition bands to achieve the + best possible quality + +partition bands: The spectrum is also broken into about + 64 "partition bands". Each partition + band is about .34 barks wide. There are about 2-5 + partition bands for each scalefactor band. + +LAME computes all psycho acoustic information for each partition +band. Then at the end of the computations, this information +is mapped to scalefactor bands. The energy in each scalefactor +band is taken as the sum of the energy in all partition bands +which overlap the scalefactor band. The maskings can be computed +in the same way (and thus represent the average masking in that band) +or by taking the minmum value multiplied by the number of +partition bands used (which represents a minimum masking in that band). + + +The general outline is as follows: + + +1. compute the energy in each partition band +2. compute the tonality in each partition band +3. compute the strength of each partion band "masker" +4. compute the masking (via the spreading function applied to each masker) +5. Modifications for mid/side masking. + +Each partition band is considiered a "masker". The strength +of the i'th masker in band j is given by: + + s3(bark(i)-bark(j))*strength(i) + +The strength of the masker is a function of the energy and tonality. +The more tonal, the less masking. LAME uses a simple linear formula +(controlled by NMT and TMN) which says the strength is given by the +energy divided by a linear function of the tonality. + + +s3() is the "spreading function". It is given by a formula +determined via listening tests. + +The total masking in the j'th partition band is the sum over +all maskings i. It is thus given by the convolution of +the strength with s3(), the "spreading function." + +masking(j) = sum_over_i s3(i-j)*strength(i) = s3 o strength + +where "o" = convolution operator. s3 is given by a formula determined +via listening tests. It is normalized so that s3 o 1 = 1. + +Note: instead of a simple convolution, LAME also has the +option of using "additive masking" + +The most critical part is step 2, computing the tonality of each +partition band. LAME has two tonality estimators. The first +is based on the ISO spec, and measures how predictiable the +signal is over time. The more predictable, the more tonal. +The second measure is based on looking at the spectrum of +a single granule. The more peaky the spectrum, the more +tonal. By most indications, the latter approach is better. + +Finally, in step 5, the maskings for the mid and side +channel are possibly increased. Under certain circumstances, +noise in the mid & side channels is assumed to also +be masked by strong maskers in the L or R channels. + + +Other data computed by the psy-model: + +ms_ratio side-channel / mid-channel masking ratio (for previous granule) +ms_ratio_next side-channel / mid-channel masking ratio for this granule + +percep_entropy[2] L and R values (prev granule) of PE - A measure of how + much pre-echo is in the previous granule +percep_entropy_MS[2] mid and side channel values (prev granule) of percep_entropy +energy[4] L,R,M,S energy in each channel, prev granule +blocktype_d[2] block type to use for previous granule + + +*/ + + + + +#include "config_static.h" + +#include "util.h" +#include "encoder.h" +#include "psymodel.h" +#include "l3side.h" +#include +#include "tables.h" +#include "fft.h" + +#ifdef WITH_DMALLOC +#include +#endif + +#define NSFIRLEN 21 +#define rpelev 2 +#define rpelev2 16 +#define rpelev_s 2 +#define rpelev2_s 16 + +/* size of each partition band, in barks: */ +#define DELBARK .34 + + +#if 1 + /* AAC values, results in more masking over MP3 values */ +# define TMN 18 +# define NMT 6 +#else + /* MP3 values */ +# define TMN 29 +# define NMT 6 +#endif + +#define NBPSY_l (SBMAX_l) +#define NBPSY_s (SBMAX_s) + + +#ifdef M_LN10 +#define LN_TO_LOG10 (M_LN10/10) +#else +#define LN_TO_LOG10 0.2302585093 +#endif + +FLOAT +psycho_loudness_approx( FLOAT *energy, lame_global_flags *gfp ); + + + + + +/* + L3psycho_anal. Compute psycho acoustics. + + Data returned to the calling program must be delayed by one + granule. + + This is done in two places. + If we do not need to know the blocktype, the copying + can be done here at the top of the program: we copy the data for + the last granule (computed during the last call) before it is + overwritten with the new data. It looks like this: + + 0. static psymodel_data + 1. calling_program_data = psymodel_data + 2. compute psymodel_data + + For data which needs to know the blocktype, the copying must be + done at the end of this loop, and the old values must be saved: + + 0. static psymodel_data_old + 1. compute psymodel_data + 2. compute possible block type of this granule + 3. compute final block type of previous granule based on #2. + 4. calling_program_data = psymodel_data_old + 5. psymodel_data_old = psymodel_data +*/ +int L3psycho_anal( lame_global_flags * gfp, + const sample_t *buffer[2], int gr_out, + FLOAT8 *ms_ratio, + FLOAT8 *ms_ratio_next, + III_psy_ratio masking_ratio[2][2], + III_psy_ratio masking_MS_ratio[2][2], + FLOAT8 percep_entropy[2],FLOAT8 percep_MS_entropy[2], + FLOAT8 energy[4], + int blocktype_d[2]) +{ +/* to get a good cache performance, one has to think about + * the sequence, in which the variables are used. + * (Note: these static variables have been moved to the gfc-> struct, + * and their order in memory is layed out in util.h) + */ + lame_internal_flags *gfc=gfp->internal_flags; + + + /* fft and energy calculation */ + FLOAT (*wsamp_l)[BLKSIZE]; + FLOAT (*wsamp_s)[3][BLKSIZE_s]; + + /* convolution */ + FLOAT8 eb[CBANDS]; + FLOAT8 cb[CBANDS]; + FLOAT8 thr[CBANDS]; + + /* ratios */ + FLOAT8 ms_ratio_l=0,ms_ratio_s=0; + + /* block type */ + int blocktype[2],uselongblock[2]; + + /* usual variables like loop indices, etc.. */ + int numchn, chn; + int b, i, j, k; + int sb,sblock; + + + if(gfc->psymodel_init==0) { + psymodel_init(gfp); + init_fft(gfc); + gfc->psymodel_init=1; + + for (chn = 0; chn < 4; ++chn ) + for (b = 0; b < CBANDS; ++b ) + gfc->nb_s1[chn][b] = gfc->nb_s2[chn][b] = 1.0; + + } + + + + + + numchn = gfc->channels_out; + /* chn=2 and 3 = Mid and Side channels */ + if (gfp->mode == JOINT_STEREO) numchn=4; + + for (chn=0; chntot_ener[chn]; + } + } + + for (chn=0; chn pe [chn]; + masking_ratio [gr_out] [chn] .en = gfc -> en [chn]; + masking_ratio [gr_out] [chn] .thm = gfc -> thm [chn]; + } else { + /* MS maskings */ + percep_MS_entropy [chn-2] = gfc -> pe [chn]; + masking_MS_ratio [gr_out] [chn-2].en = gfc -> en [chn]; + masking_MS_ratio [gr_out] [chn-2].thm = gfc -> thm [chn]; + } + + + + /********************************************************************** + * compute FFTs + **********************************************************************/ + wsamp_s = gfc->wsamp_S+(chn & 1); + wsamp_l = gfc->wsamp_L+(chn & 1); + if (chn<2) { + fft_long ( gfc, *wsamp_l, chn, buffer); + fft_short( gfc, *wsamp_s, chn, buffer); + } + /* FFT data for mid and side channel is derived from L & R */ + if (chn == 2) + { + for (j = BLKSIZE-1; j >=0 ; --j) + { + FLOAT l = gfc->wsamp_L[0][j]; + FLOAT r = gfc->wsamp_L[1][j]; + gfc->wsamp_L[0][j] = (l+r)*(FLOAT)(SQRT2*0.5); + gfc->wsamp_L[1][j] = (l-r)*(FLOAT)(SQRT2*0.5); + } + for (b = 2; b >= 0; --b) + { + for (j = BLKSIZE_s-1; j >= 0 ; --j) + { + FLOAT l = gfc->wsamp_S[0][b][j]; + FLOAT r = gfc->wsamp_S[1][b][j]; + gfc->wsamp_S[0][b][j] = (l+r)*(FLOAT)(SQRT2*0.5); + gfc->wsamp_S[1][b][j] = (l-r)*(FLOAT)(SQRT2*0.5); + } + } + } + + + /********************************************************************** + * compute energies + **********************************************************************/ + + + + gfc->energy[0] = (*wsamp_l)[0]; + gfc->energy[0] *= gfc->energy[0]; + + gfc->tot_ener[chn] = gfc->energy[0]; /* sum total energy at nearly no extra cost */ + + for (j=BLKSIZE/2-1; j >= 0; --j) + { + FLOAT re = (*wsamp_l)[BLKSIZE/2-j]; + FLOAT im = (*wsamp_l)[BLKSIZE/2+j]; + gfc->energy[BLKSIZE/2-j] = (re * re + im * im) * (FLOAT)0.5; + + if (BLKSIZE/2-j > 10) + gfc->tot_ener[chn] += gfc->energy[BLKSIZE/2-j]; + } + for (b = 2; b >= 0; --b) + { + gfc->energy_s[b][0] = (*wsamp_s)[b][0]; + gfc->energy_s[b][0] *= gfc->energy_s [b][0]; + for (j=BLKSIZE_s/2-1; j >= 0; --j) + { + FLOAT re = (*wsamp_s)[b][BLKSIZE_s/2-j]; + FLOAT im = (*wsamp_s)[b][BLKSIZE_s/2+j]; + gfc->energy_s[b][BLKSIZE_s/2-j] = (re * re + im * im) * (FLOAT)0.5; + } + } + +#if defined(HAVE_GTK) + if (gfp->analysis) { + for (j=0; jpinfo->energy[gr_out][chn][j]=gfc->energy_save[chn][j]; + gfc->energy_save[chn][j]=gfc->energy[j]; + } + } +#endif + + + + /********************************************************************** + * compute loudness approximation (used for ATH auto-level adjustment) + **********************************************************************/ + if( gfp->athaa_loudapprox == 2 ) { + if( chn < 2 ) { /* no loudness for mid and side channels */ + gfc->loudness_sq[gr_out][chn] = gfc->loudness_sq_save[chn]; + gfc->loudness_sq_save[chn] + = psycho_loudness_approx( gfc->energy, gfp); + } + } + + + + /********************************************************************** + * compute unpredicatability of first six spectral lines * + **********************************************************************/ + for ( j = 0; j < gfc->cw_lower_index; j++ ) + { /* calculate unpredictability measure cw */ + FLOAT an, a1, a2; + FLOAT bn, b1, b2; + FLOAT rn, r1, r2; + FLOAT numre, numim, den; + + a2 = gfc-> ax_sav[chn][1][j]; + b2 = gfc-> bx_sav[chn][1][j]; + r2 = gfc-> rx_sav[chn][1][j]; + a1 = gfc-> ax_sav[chn][1][j] = gfc-> ax_sav[chn][0][j]; + b1 = gfc-> bx_sav[chn][1][j] = gfc-> bx_sav[chn][0][j]; + r1 = gfc-> rx_sav[chn][1][j] = gfc-> rx_sav[chn][0][j]; + an = gfc-> ax_sav[chn][0][j] = (*wsamp_l)[j]; + bn = gfc-> bx_sav[chn][0][j] = j==0 ? (*wsamp_l)[0] : (*wsamp_l)[BLKSIZE-j]; + rn = gfc-> rx_sav[chn][0][j] = sqrt(gfc->energy[j]); + + { /* square (x1,y1) */ + if( r1 != 0 ) { + numre = (a1*b1); + numim = (a1*a1-b1*b1)*(FLOAT)0.5; + den = r1*r1; + } else { + numre = 1; + numim = 0; + den = 1; + } + } + + { /* multiply by (x2,-y2) */ + if( r2 != 0 ) { + FLOAT tmp2 = (numim+numre)*(a2+b2)*(FLOAT)0.5; + FLOAT tmp1 = -a2*numre+tmp2; + numre = -b2*numim+tmp2; + numim = tmp1; + den *= r2; + } else { + /* do nothing */ + } + } + + { /* r-prime factor */ + FLOAT tmp = (2*r1-r2)/den; + numre *= tmp; + numim *= tmp; + } + den=rn+fabs(2*r1-r2); + if( den != 0 ) { + numre = (an+bn)*(FLOAT)0.5-numre; + numim = (an-bn)*(FLOAT)0.5-numim; + den = sqrt(numre*numre+numim*numim)/den; + } + gfc->cw[j] = den; + } + + + + /********************************************************************** + * compute unpredicatibility of next 200 spectral lines * + **********************************************************************/ + for ( j = gfc->cw_lower_index; j < gfc->cw_upper_index; j += 4 ) + {/* calculate unpredictability measure cw */ + FLOAT rn, r1, r2; + FLOAT numre, numim, den; + + k = (j+2) / 4; + + { /* square (x1,y1) */ + r1 = gfc->energy_s[0][k]; + if( r1 != 0 ) { + FLOAT a1 = (*wsamp_s)[0][k]; + FLOAT b1 = (*wsamp_s)[0][BLKSIZE_s-k]; /* k is never 0 */ + numre = (a1*b1); + numim = (a1*a1-b1*b1)*(FLOAT)0.5; + den = r1; + r1 = sqrt(r1); + } else { + numre = 1; + numim = 0; + den = 1; + } + } + + + { /* multiply by (x2,-y2) */ + r2 = gfc->energy_s[2][k]; + if( r2 != 0 ) { + FLOAT a2 = (*wsamp_s)[2][k]; + FLOAT b2 = (*wsamp_s)[2][BLKSIZE_s-k]; + + + FLOAT tmp2 = (numim+numre)*(a2+b2)*(FLOAT)0.5; + FLOAT tmp1 = -a2*numre+tmp2; + numre = -b2*numim+tmp2; + numim = tmp1; + + r2 = sqrt(r2); + den *= r2; + } else { + /* do nothing */ + } + } + + { /* r-prime factor */ + FLOAT tmp = (2*r1-r2)/den; + numre *= tmp; + numim *= tmp; + } + + rn = sqrt(gfc->energy_s[1][k]); + den=rn+fabs(2*r1-r2); + if( den != 0 ) { + FLOAT an = (*wsamp_s)[1][k]; + FLOAT bn = (*wsamp_s)[1][BLKSIZE_s-k]; + numre = (an+bn)*(FLOAT)0.5-numre; + numim = (an-bn)*(FLOAT)0.5-numim; + den = sqrt(numre*numre+numim*numim)/den; + } + + gfc->cw[j+1] = gfc->cw[j+2] = gfc->cw[j+3] = gfc->cw[j] = den; + } + +#if 0 + for ( j = 14; j < HBLKSIZE-4; j += 4 ) + {/* calculate energy from short ffts */ + FLOAT8 tot,ave; + k = (j+2) / 4; + for (tot=0, sblock=0; sblock < 3; sblock++) + tot+=gfc->energy_s[sblock][k]; + ave = gfc->energy[j+1]+ gfc->energy[j+2]+ gfc->energy[j+3]+ gfc->energy[j]; + ave /= 4.; + gfc->energy[j+1] = gfc->energy[j+2] = gfc->energy[j+3] = gfc->energy[j]=tot; + } +#endif + + /********************************************************************** + * Calculate the energy and the unpredictability in the threshold * + * calculation partitions * + **********************************************************************/ + + b = 0; + for (j = 0; j < gfc->cw_upper_index && gfc->numlines_l[b] && bnpart_l_orig; ) + { + FLOAT8 ebb, cbb; + + ebb = gfc->energy[j]; + cbb = gfc->energy[j] * gfc->cw[j]; + j++; + + for (i = gfc->numlines_l[b] - 1; i > 0; i--) + { + ebb += gfc->energy[j]; + cbb += gfc->energy[j] * gfc->cw[j]; + j++; + } + eb[b] = ebb; + cb[b] = cbb; + b++; + } + + for (; b < gfc->npart_l_orig; b++ ) + { + FLOAT8 ebb = gfc->energy[j++]; + assert(gfc->numlines_l[b]); + for (i = gfc->numlines_l[b] - 1; i > 0; i--) + { + ebb += gfc->energy[j++]; + } + eb[b] = ebb; + cb[b] = ebb * 0.4; + } + + /********************************************************************** + * convolve the partitioned energy and unpredictability * + * with the spreading function, s3_l[b][k](packed into s3_ll) * + ******************************************************************** */ + gfc->pe[chn] = 0; /* calculate percetual entropy */ + { + int kk = 0; + for ( b = 0;b < gfc->npart_l; b++ ) + { + FLOAT8 tbb,ecb,ctb; + + ecb = 0; + ctb = 0; + + for ( k = gfc->s3ind[b][0]; k <= gfc->s3ind[b][1]; k++ ) + { + ecb += gfc->s3_ll[kk] * eb[k]; /* sprdngf for Layer III */ + ctb += gfc->s3_ll[kk] * cb[k]; + kk++; + } + + /* calculate the tonality of each threshold calculation partition + * calculate the SNR in each threshold calculation partition + * tonality = -0.299 - .43*log(ctb/ecb); + * tonality = 0: use NMT (lots of masking) + * tonality = 1: use TMN (little masking) + */ + +/* ISO values */ +#define CONV1 (-.299) +#define CONV2 (-.43) + + tbb = ecb; + if (tbb != 0) + { + tbb = ctb / tbb; + if (tbb <= exp((1-CONV1)/CONV2)) + { /* tonality near 1 */ + tbb = exp(-LN_TO_LOG10 * TMN); + } + else if (tbb >= exp((0-CONV1)/CONV2)) + {/* tonality near 0 */ + tbb = exp(-LN_TO_LOG10 * NMT); + } + else + { + /* convert to tonality index */ + /* tonality small: tbb=1 */ + /* tonality large: tbb=-.299 */ + tbb = CONV1 + CONV2*log(tbb); + tbb = exp(-LN_TO_LOG10 * ( TMN*tbb + (1-tbb)*NMT) ); + } + } + + /* at this point, tbb represents the amount the spreading function + * will be reduced. The smaller the value, the less masking. + * minval[] = 1 (0db) says just use tbb. + * minval[]= .01 (-20db) says reduce spreading function by + * at least 20db. + */ + + tbb = Min(gfc->minval[b], tbb); + + /* stabilize tonality estimation */ + if ( gfc->PSY->tonalityPatch ) { + if ( b > 5 ) + { + FLOAT8 const x = 1.8699422; + FLOAT8 w = gfc->PSY->prvTonRed[b/2] * x; + if (tbb > w) + tbb = w; + } + gfc->PSY->prvTonRed[b] = tbb; + } + + ecb *= tbb; + + /* long block pre-echo control. */ + /* rpelev=2.0, rpelev2=16.0 */ + /* note: all surges in PE are because of this pre-echo formula + * for thr[b]. If it this is not used, PE is always around 600 + */ + /* dont use long block pre-echo control if previous granule was + * a short block. This is to avoid the situation: + * frame0: quiet (very low masking) + * frame1: surge (triggers short blocks) + * frame2: regular frame. looks like pre-echo when compared to + * frame0, but all pre-echo was in frame1. + */ + /* chn=0,1 L and R channels + chn=2,3 S and M channels. + */ + + if (gfc->blocktype_old[chn>1 ? chn-2 : chn] == SHORT_TYPE ) + thr[b] = ecb; /* Min(ecb, rpelev*gfc->nb_1[chn][b]); */ + else + thr[b] = Min(ecb, Min(rpelev*gfc->nb_1[chn][b],rpelev2*gfc->nb_2[chn][b]) ); + + { + FLOAT8 thrpe; + thrpe = Max(thr[b],gfc->ATH->cb[b]); + /* + printf("%i thr=%e ATH=%e \n",b,thr[b],gfc->ATH->cb[b]); + */ + if (thrpe < eb[b]) + gfc->pe[chn] -= gfc->numlines_l[b] * log(thrpe / eb[b]); + } + + if ( gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh ) { + thr[b] = Min(ecb, rpelev*gfc->nb_1[chn][b]); + if (gfc->blocktype_old[chn>1 ? chn-2 : chn] != SHORT_TYPE ) + thr[b] = Min(thr[b], rpelev2*gfc->nb_2[chn][b]); + thr[b] = Max( thr[b], 1e-37 ); + } + + gfc->nb_2[chn][b] = gfc->nb_1[chn][b]; + gfc->nb_1[chn][b] = ecb; + } + } + + /*************************************************************** + * determine the block type (window type) based on L & R channels + * + ***************************************************************/ + { /* compute PE for all 4 channels */ + FLOAT mn,mx,ma=0,mb=0,mc=0; + + for ( j = HBLKSIZE_s/2; j < HBLKSIZE_s; j ++) + { + ma += gfc->energy_s[0][j]; + mb += gfc->energy_s[1][j]; + mc += gfc->energy_s[2][j]; + } + mn = Min(ma,mb); + mn = Min(mn,mc); + mx = Max(ma,mb); + mx = Max(mx,mc); + + /* bit allocation is based on pe. */ + if (mx>mn) { + FLOAT8 tmp = 400*log(mx/(1e-12+mn)); + if (tmp>gfc->pe[chn]) gfc->pe[chn]=tmp; + } + + /* block type is based just on L or R channel */ + if (chn<2) { + uselongblock[chn] = 1; + + /* tuned for t1.wav. doesnt effect most other samples */ + if (gfc->pe[chn] > 3000) + uselongblock[chn]=0; + + if ( mx > 30*mn ) + {/* big surge of energy - always use short blocks */ + uselongblock[chn] = 0; + } + else if ((mx > 10*mn) && (gfc->pe[chn] > 1000)) + {/* medium surge, medium pe - use short blocks */ + uselongblock[chn] = 0; + } + + /* disable short blocks */ + if (gfp->short_blocks == short_block_dispensed) + uselongblock[chn]=1; + if (gfp->short_blocks == short_block_forced) + uselongblock[chn]=0; + } + } + +#if defined(HAVE_GTK) + if (gfp->analysis) { + FLOAT mn,mx,ma=0,mb=0,mc=0; + + for ( j = HBLKSIZE_s/2; j < HBLKSIZE_s; j ++) + { + ma += gfc->energy_s[0][j]; + mb += gfc->energy_s[1][j]; + mc += gfc->energy_s[2][j]; + } + mn = Min(ma,mb); + mn = Min(mn,mc); + mx = Max(ma,mb); + mx = Max(mx,mc); + + gfc->pinfo->ers[gr_out][chn]=gfc->ers_save[chn]; + gfc->ers_save[chn]=(mx/(1e-12+mn)); + gfc->pinfo->pe[gr_out][chn]=gfc->pe_save[chn]; + gfc->pe_save[chn]=gfc->pe[chn]; + } +#endif + + + /*************************************************************** + * compute masking thresholds for both short and long blocks + ***************************************************************/ + /* longblock threshold calculation (part 2) */ + for ( sb = 0; sb < NBPSY_l; sb++ ) + { + FLOAT8 enn = gfc->w1_l[sb] * eb[gfc->bu_l[sb]] + gfc->w2_l[sb] * eb[gfc->bo_l[sb]]; + FLOAT8 thmm = gfc->w1_l[sb] *thr[gfc->bu_l[sb]] + gfc->w2_l[sb] * thr[gfc->bo_l[sb]]; + + for ( b = gfc->bu_l[sb]+1; b < gfc->bo_l[sb]; b++ ) + { + enn += eb[b]; + thmm += thr[b]; + } + + gfc->en [chn].l[sb] = enn; + gfc->thm[chn].l[sb] = thmm; + } + + + /* threshold calculation for short blocks */ + for ( sblock = 0; sblock < 3; sblock++ ) + { + j = 0; + for ( b = 0; b < gfc->npart_s_orig; b++ ) + { + FLOAT ecb = gfc->energy_s[sblock][j++]; + for (i = 1 ; inumlines_s[b]; ++i) + { + ecb += gfc->energy_s[sblock][j++]; + } + eb[b] = ecb; + } + { + int kk = 0; + for ( b = 0; b < gfc->npart_s; b++ ) + { + FLOAT8 ecb = 0; + for ( k = gfc->s3ind_s[b][0]; k <= gfc->s3ind_s[b][1]; k++ ) { + ecb += gfc->s3_ss[kk++] * eb[k]; + } + ecb *= gfc->SNR_s[b]; + +/* 2001-07-13 */ + if ( gfp->VBR == vbr_off || gfp->VBR == vbr_abr ) { + /* this looks like a BUG to me. robert */ + thr[b] = Max (1e-6, ecb); + } + else { + thr[b] = Min( ecb, rpelev_s * gfc->nb_s1[chn][b] ); + if (gfc->blocktype_old[chn>1 ? chn-2 : chn] == SHORT_TYPE ) { + thr[b] = Min( thr[b], rpelev2_s * gfc->nb_s2[chn][b] ); + } + thr[b] = Max( thr[b], 1e-37 ); + gfc->nb_s2[chn][b] = gfc->nb_s1[chn][b]; + gfc->nb_s1[chn][b] = ecb; + } + + } + + for ( sb = 0; sb < NBPSY_s; sb++ ) + { + FLOAT8 enn = gfc->w1_s[sb] * eb[gfc->bu_s[sb]] + gfc->w2_s[sb] * eb[gfc->bo_s[sb]]; + FLOAT8 thmm = gfc->w1_s[sb] *thr[gfc->bu_s[sb]] + gfc->w2_s[sb] * thr[gfc->bo_s[sb]]; + + for ( b = gfc->bu_s[sb]+1; b < gfc->bo_s[sb]; b++ ) { + enn += eb[b]; + thmm += thr[b]; + } + + gfc->en [chn].s[sb][sblock] = enn; + gfc->thm[chn].s[sb][sblock] = thmm; + } + } + } + } /* end loop over chn */ + + + + /*************************************************************** + * compute M/S thresholds + ***************************************************************/ + /* compute M/S thresholds from Johnston & Ferreira 1992 ICASSP paper */ + if (gfp->mode == JOINT_STEREO) { + FLOAT8 rside,rmid,mld; + int chmid=2,chside=3; + + for ( sb = 0; sb < NBPSY_l; sb++ ) { + /* use this fix if L & R masking differs by 2db or less */ + /* if db = 10*log10(x2/x1) < 2 */ + /* if (x2 < 1.58*x1) { */ + if (gfc->thm[0].l[sb] <= 1.58*gfc->thm[1].l[sb] + && gfc->thm[1].l[sb] <= 1.58*gfc->thm[0].l[sb]) { + + mld = gfc->mld_l[sb]*gfc->en[chside].l[sb]; + rmid = Max(gfc->thm[chmid].l[sb], Min(gfc->thm[chside].l[sb],mld)); + + mld = gfc->mld_l[sb]*gfc->en[chmid].l[sb]; + rside = Max(gfc->thm[chside].l[sb],Min(gfc->thm[chmid].l[sb],mld)); + + gfc->thm[chmid].l[sb]=rmid; + gfc->thm[chside].l[sb]=rside; + } + } + for ( sb = 0; sb < NBPSY_s; sb++ ) { + for ( sblock = 0; sblock < 3; sblock++ ) { + if (gfc->thm[0].s[sb][sblock] <= 1.58*gfc->thm[1].s[sb][sblock] + && gfc->thm[1].s[sb][sblock] <= 1.58*gfc->thm[0].s[sb][sblock]) { + + mld = gfc->mld_s[sb]*gfc->en[chside].s[sb][sblock]; + rmid = Max(gfc->thm[chmid].s[sb][sblock],Min(gfc->thm[chside].s[sb][sblock],mld)); + + mld = gfc->mld_s[sb]*gfc->en[chmid].s[sb][sblock]; + rside = Max(gfc->thm[chside].s[sb][sblock],Min(gfc->thm[chmid].s[sb][sblock],mld)); + + gfc->thm[chmid].s[sb][sblock]=rmid; + gfc->thm[chside].s[sb][sblock]=rside; + } + } + } + } + + + + /*************************************************************** + * Adjust M/S maskings if user set "msfix" + ***************************************************************/ + /* Naoki Shibata 2000 */ + if (numchn == 4 && gfp->msfix!=0) { + FLOAT msfix = gfp->msfix; + + for ( sb = 0; sb < NBPSY_l; sb++ ) + { + FLOAT8 thmL,thmR,thmM,thmS,ath; + ath = (gfc->ATH->cb[(gfc->bu_l[sb] + gfc->bo_l[sb])/2])*pow(10,-gfp->ATHlower/10.0); + thmL = Max(gfc->thm[0].l[sb],ath); + thmR = Max(gfc->thm[1].l[sb],ath); + thmM = Max(gfc->thm[2].l[sb],ath); + thmS = Max(gfc->thm[3].l[sb],ath); + + if (thmL*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmL*msfix / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + if (thmR*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmR*msfix / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + + gfc->thm[2].l[sb] = Min(thmM,gfc->thm[2].l[sb]); + gfc->thm[3].l[sb] = Min(thmS,gfc->thm[3].l[sb]); + } + + for ( sb = 0; sb < NBPSY_s; sb++ ) { + for ( sblock = 0; sblock < 3; sblock++ ) { + FLOAT8 thmL,thmR,thmM,thmS,ath; + ath = (gfc->ATH->cb[(gfc->bu_s[sb] + gfc->bo_s[sb])/2])*pow(10,-gfp->ATHlower/10.0); + thmL = Max(gfc->thm[0].s[sb][sblock],ath); + thmR = Max(gfc->thm[1].s[sb][sblock],ath); + thmM = Max(gfc->thm[2].s[sb][sblock],ath); + thmS = Max(gfc->thm[3].s[sb][sblock],ath); + + if (thmL*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmL*msfix / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + if (thmR*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmR*msfix / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + + gfc->thm[2].s[sb][sblock] = Min(gfc->thm[2].s[sb][sblock],thmM); + gfc->thm[3].s[sb][sblock] = Min(gfc->thm[3].s[sb][sblock],thmS); + } + } + } + + + + + + + + + + + + if (gfp->mode == JOINT_STEREO) { + /* determin ms_ratio from masking thresholds*/ + /* use ms_stereo (ms_ratio < .35) if average thresh. diff < 5 db */ + FLOAT8 db,x1,x2,sidetot=0,tot=0; + for (sb= NBPSY_l/4 ; sb< NBPSY_l; sb ++ ) { + x1 = Min(gfc->thm[0].l[sb],gfc->thm[1].l[sb]); + x2 = Max(gfc->thm[0].l[sb],gfc->thm[1].l[sb]); + /* thresholds difference in db */ + if (x2 >= 1000*x1) db=3; + else db = log10(x2/x1); + /* DEBUGF(gfc,"db = %f %e %e \n",db,gfc->thm[0].l[sb],gfc->thm[1].l[sb]);*/ + sidetot += db; + tot++; + } + ms_ratio_l= (sidetot/tot)*0.7; /* was .35*(sidetot/tot)/5.0*10 */ + ms_ratio_l = Min(ms_ratio_l,0.5); + + sidetot=0; tot=0; + for ( sblock = 0; sblock < 3; sblock++ ) + for ( sb = NBPSY_s/4; sb < NBPSY_s; sb++ ) { + x1 = Min(gfc->thm[0].s[sb][sblock],gfc->thm[1].s[sb][sblock]); + x2 = Max(gfc->thm[0].s[sb][sblock],gfc->thm[1].s[sb][sblock]); + /* thresholds difference in db */ + if (x2 >= 1000*x1) db=3; + else db = log10(x2/x1); + sidetot += db; + tot++; + } + ms_ratio_s = (sidetot/tot)*0.7; /* was .35*(sidetot/tot)/5.0*10 */ + ms_ratio_s = Min(ms_ratio_s,.5); + } + + /*************************************************************** + * determine final block type + ***************************************************************/ + + for (chn=0; chnchannels_out; chn++) { + blocktype[chn] = NORM_TYPE; + } + + + if (gfp->short_blocks == short_block_coupled) { + /* force both channels to use the same block type */ + /* this is necessary if the frame is to be encoded in ms_stereo. */ + /* But even without ms_stereo, FhG does this */ + int bothlong= (uselongblock[0] && uselongblock[1]); + if (!bothlong) { + uselongblock[0]=0; + uselongblock[1]=0; + } + } + + + + /* update the blocktype of the previous granule, since it depends on what + * happend in this granule */ + for (chn=0; chnchannels_out; chn++) { + if ( uselongblock[chn]) + { /* no attack : use long blocks */ + assert( gfc->blocktype_old[chn] != START_TYPE ); + switch( gfc->blocktype_old[chn] ) + { + case NORM_TYPE: + case STOP_TYPE: + blocktype[chn] = NORM_TYPE; + break; + case SHORT_TYPE: + blocktype[chn] = STOP_TYPE; + break; + } + } else { + /* attack : use short blocks */ + blocktype[chn] = SHORT_TYPE; + if ( gfc->blocktype_old[chn] == NORM_TYPE ) { + gfc->blocktype_old[chn] = START_TYPE; + } + if ( gfc->blocktype_old[chn] == STOP_TYPE ) { + gfc->blocktype_old[chn] = SHORT_TYPE ; + } + } + + blocktype_d[chn] = gfc->blocktype_old[chn]; /* value returned to calling program */ + gfc->blocktype_old[chn] = blocktype[chn]; /* save for next call to l3psy_anal */ + } + + if (blocktype_d[0]==2 && blocktype_d[1]==2) + *ms_ratio = gfc->ms_ratio_s_old; + else + *ms_ratio = gfc->ms_ratio_l_old; + + gfc->ms_ratio_s_old = ms_ratio_s; + gfc->ms_ratio_l_old = ms_ratio_l; + + /* we dont know the block type of this frame yet - assume long */ + *ms_ratio_next = ms_ratio_l; + + return 0; +} + +/* addition of simultaneous masking Naoki Shibata 2000/7 */ +inline static FLOAT8 mask_add(FLOAT8 m1,FLOAT8 m2,int k,int b, lame_internal_flags * const gfc) +{ + static const FLOAT8 table1[] = { + 3.3246 *3.3246 ,3.23837*3.23837,3.15437*3.15437,3.00412*3.00412,2.86103*2.86103,2.65407*2.65407,2.46209*2.46209,2.284 *2.284 , + 2.11879*2.11879,1.96552*1.96552,1.82335*1.82335,1.69146*1.69146,1.56911*1.56911,1.46658*1.46658,1.37074*1.37074,1.31036*1.31036, + 1.25264*1.25264,1.20648*1.20648,1.16203*1.16203,1.12765*1.12765,1.09428*1.09428,1.0659 *1.0659 ,1.03826*1.03826,1.01895*1.01895, + 1 + }; + + static const FLOAT8 table2[] = { + 1.33352*1.33352,1.35879*1.35879,1.38454*1.38454,1.39497*1.39497,1.40548*1.40548,1.3537 *1.3537 ,1.30382*1.30382,1.22321*1.22321, + 1.14758*1.14758 + }; + + static const FLOAT8 table3[] = { + 2.35364*2.35364,2.29259*2.29259,2.23313*2.23313,2.12675*2.12675,2.02545*2.02545,1.87894*1.87894,1.74303*1.74303,1.61695*1.61695, + 1.49999*1.49999,1.39148*1.39148,1.29083*1.29083,1.19746*1.19746,1.11084*1.11084,1.03826*1.03826 + }; + + + int i; + FLOAT8 m; + + if (m1 == 0) return m2; + + if (b < 0) b = -b; + + i = 10*log10(m2 / m1)/10*16; + m = 10*log10((m1+m2)/gfc->ATH->cb[k]); + + if (i < 0) i = -i; + + if (b <= 3) { /* approximately, 1 bark = 3 partitions */ + if (i > 8) return m1+m2; + return (m1+m2)*table2[i]; + } + + if (m<15) { + if (m > 0) { + FLOAT8 f=1.0,r; + if (i > 24) return m1+m2; + if (i > 13) f = 1; else f = table3[i]; + r = (m-0)/15; + return (m1+m2)*(table1[i]*r+f*(1-r)); + } + if (i > 13) return m1+m2; + return (m1+m2)*table3[i]; + } + + if (i > 24) return m1+m2; + return (m1+m2)*table1[i]; +} + +int L3psycho_anal_ns( lame_global_flags * gfp, + const sample_t *buffer[2], int gr_out, + FLOAT8 *ms_ratio, + FLOAT8 *ms_ratio_next, + III_psy_ratio masking_ratio[2][2], + III_psy_ratio masking_MS_ratio[2][2], + FLOAT8 percep_entropy[2],FLOAT8 percep_MS_entropy[2], + FLOAT8 energy[4], + int blocktype_d[2]) +{ +/* to get a good cache performance, one has to think about + * the sequence, in which the variables are used. + * (Note: these static variables have been moved to the gfc-> struct, + * and their order in memory is layed out in util.h) + */ + lame_internal_flags *gfc=gfp->internal_flags; + + /* fft and energy calculation */ + FLOAT (*wsamp_l)[BLKSIZE]; + FLOAT (*wsamp_s)[3][BLKSIZE_s]; + + /* convolution */ + FLOAT8 eb[CBANDS],eb2[CBANDS]; + FLOAT8 thr[CBANDS]; + + FLOAT8 max[CBANDS],avg[CBANDS],tonality2[CBANDS]; + + /* ratios */ + FLOAT8 ms_ratio_l=0,ms_ratio_s=0; + + /* block type */ + int blocktype[2],uselongblock[2]; + + /* usual variables like loop indices, etc.. */ + int numchn, chn; + int b, i, j, k; + int sb,sblock; + + /* variables used for --nspsytune */ + int ns_attacks[4]; + FLOAT ns_hpfsmpl[4][576+576/3+NSFIRLEN]; + FLOAT pe_l[4],pe_s[4]; + FLOAT pcfact; + + + if(gfc->psymodel_init==0) { + psymodel_init(gfp); + init_fft(gfc); + gfc->psymodel_init=1; + } + + + numchn = gfc->channels_out; + /* chn=2 and 3 = Mid and Side channels */ + if (gfp->mode == JOINT_STEREO) numchn=4; + + if (gfp->VBR==vbr_off) pcfact = gfc->ResvMax == 0 ? 0 : ((FLOAT)gfc->ResvSize)/gfc->ResvMax*0.5; + else if (gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh || gfp->VBR == vbr_mt) { + static const FLOAT8 pcQns[10]={1.0,1.0,1.0,0.8,0.6,0.5,0.4,0.3,0.2,0.1}; + pcfact = pcQns[gfp->VBR_q]; + } else pcfact = 1; + + /********************************************************************** + * Apply HPF of fs/4 to the input signal. + * This is used for attack detection / handling. + **********************************************************************/ + + { + static const FLOAT fircoef[] = { + -8.65163e-18,-0.00851586,-6.74764e-18, 0.0209036, + -3.36639e-17,-0.0438162 ,-1.54175e-17, 0.0931738, + -5.52212e-17,-0.313819 , 0.5 ,-0.313819, + -5.52212e-17, 0.0931738 ,-1.54175e-17,-0.0438162, + -3.36639e-17, 0.0209036 ,-6.74764e-18,-0.00851586, + -8.65163e-18, + }; + + for(chn=0;chnchannels_out;chn++) + { + FLOAT firbuf[576+576/3+NSFIRLEN]; + + /* apply high pass filter of fs/4 */ + + for(i=-NSFIRLEN;i<576+576/3;i++) + firbuf[i+NSFIRLEN] = buffer[chn][576-350+(i)]; + + for(i=0;i<576+576/3-NSFIRLEN;i++) + { + FLOAT sum = 0; + for(j=0;jmode == JOINT_STEREO) { + for(i=0;i<576+576/3;i++) + { + ns_hpfsmpl[2][i] = ns_hpfsmpl[0][i]+ns_hpfsmpl[1][i]; + ns_hpfsmpl[3][i] = ns_hpfsmpl[0][i]-ns_hpfsmpl[1][i]; + } + } + } + + + + /* there is a one granule delay. Copy maskings computed last call + * into masking_ratio to return to calling program. + */ + for (chn=0; chntot_ener[chn]; + } + } + + + for (chn=0; chnnsPsy.pe_l[chn]; + pe_s[chn] = gfc->nsPsy.pe_s[chn]; + + if (chn < 2) { + /* LR maskings */ + //percep_entropy [chn] = gfc -> pe [chn]; + masking_ratio [gr_out] [chn] .en = gfc -> en [chn]; + masking_ratio [gr_out] [chn] .thm = gfc -> thm [chn]; + } else { + /* MS maskings */ + //percep_MS_entropy [chn-2] = gfc -> pe [chn]; + masking_MS_ratio [gr_out] [chn-2].en = gfc -> en [chn]; + masking_MS_ratio [gr_out] [chn-2].thm = gfc -> thm [chn]; + } + } + + for (chn=0; chnwsamp_S+(chn & 1); + wsamp_l = gfc->wsamp_L+(chn & 1); + + if (chn<2) { + fft_long ( gfc, *wsamp_l, chn, buffer); + fft_short( gfc, *wsamp_s, chn, buffer); + } + + /* FFT data for mid and side channel is derived from L & R */ + + if (chn == 2) + { + for (j = BLKSIZE-1; j >=0 ; --j) + { + FLOAT l = gfc->wsamp_L[0][j]; + FLOAT r = gfc->wsamp_L[1][j]; + gfc->wsamp_L[0][j] = (l+r)*(FLOAT)(SQRT2*0.5); + gfc->wsamp_L[1][j] = (l-r)*(FLOAT)(SQRT2*0.5); + } + for (b = 2; b >= 0; --b) + { + for (j = BLKSIZE_s-1; j >= 0 ; --j) + { + FLOAT l = gfc->wsamp_S[0][b][j]; + FLOAT r = gfc->wsamp_S[1][b][j]; + gfc->wsamp_S[0][b][j] = (l+r)*(FLOAT)(SQRT2*0.5); + gfc->wsamp_S[1][b][j] = (l-r)*(FLOAT)(SQRT2*0.5); + } + } + } + + + /********************************************************************** + * compute energies for each spectral line + **********************************************************************/ + + /* long block */ + + gfc->energy[0] = (*wsamp_l)[0]; + gfc->energy[0] *= gfc->energy[0]; + + gfc->tot_ener[chn] = gfc->energy[0]; /* sum total energy at nearly no extra cost */ + + for (j=BLKSIZE/2-1; j >= 0; --j) + { + FLOAT re = (*wsamp_l)[BLKSIZE/2-j]; + FLOAT im = (*wsamp_l)[BLKSIZE/2+j]; + gfc->energy[BLKSIZE/2-j] = (re * re + im * im) * (FLOAT)0.5; + + if (BLKSIZE/2-j > 10) + gfc->tot_ener[chn] += gfc->energy[BLKSIZE/2-j]; + } + + + /* short block */ + + for (b = 2; b >= 0; --b) + { + gfc->energy_s[b][0] = (*wsamp_s)[b][0]; + gfc->energy_s[b][0] *= gfc->energy_s [b][0]; + for (j=BLKSIZE_s/2-1; j >= 0; --j) + { + FLOAT re = (*wsamp_s)[b][BLKSIZE_s/2-j]; + FLOAT im = (*wsamp_s)[b][BLKSIZE_s/2+j]; + gfc->energy_s[b][BLKSIZE_s/2-j] = (re * re + im * im) * (FLOAT)0.5; + } + } + + + /* output data for analysis */ + +#if defined(HAVE_GTK) + if (gfp->analysis) { + for (j=0; jpinfo->energy[gr_out][chn][j]=gfc->energy_save[chn][j]; + gfc->energy_save[chn][j]=gfc->energy[j]; + } + } +#endif + + + /********************************************************************** + * compute loudness approximation (used for ATH auto-level adjustment) + **********************************************************************/ + if( gfp->athaa_loudapprox == 2 ) { + if( chn < 2 ) { /* no loudness for mid and side channels */ + gfc->loudness_sq[gr_out][chn] = gfc->loudness_sq_save[chn]; + gfc->loudness_sq_save[chn] + = psycho_loudness_approx( gfc->energy, gfp); + } + } + + + + /********************************************************************** + * Calculate the energy and the tonality of each partition. + **********************************************************************/ + + for (b=0, j=0; bnpart_l_orig; b++) + { + FLOAT8 ebb,m,a; + + ebb = gfc->energy[j]; + m = a = gfc->energy[j]; + j++; + + for (i = gfc->numlines_l[b] - 1; i > 0; i--) + { + FLOAT8 el = gfc->energy[j]; + ebb += gfc->energy[j]; + a += el; + m = m < el ? el : m; + j++; + } + eb[b] = ebb; + max[b] = m; + avg[b] = a / gfc->numlines_l[b]; + } + + j = 0; + for (b=0; b < gfc->npart_l_orig; b++ ) + { + int c1,c2; + FLOAT8 m,a; + tonality2[b] = 0; + c1 = c2 = 0; + m = a = 0; + for(k=b-1;k<=b+1;k++) + { + if (k >= 0 && k < gfc->npart_l_orig) { + c1++; + c2 += gfc->numlines_l[k]; + a += avg[k]; + m = m < max[k] ? max[k] : m; + } + } + + a /= c1; + tonality2[b] = a == 0 ? 0 : (m / a - 1)/(c2-1); + } + + for (b=0; b < gfc->npart_l_orig; b++ ) + { +#if 0 + static FLOAT8 tab[20] = + { 0, 1, 2, 2, 2, 2, 2, 6,9.3,9.3,9.3,9.3,9.3,9.3,9.3,9.3,9.3,9.3,9.3,9.3}; + + static int init = 1; + if (init) { + int j; + for(j=0;j<20;j++) { + tab[j] = pow(10.0,-tab[j]/10.0); + } + init = 0; + } +#else + static FLOAT8 tab[20] = { + 1,0.79433,0.63096,0.63096,0.63096,0.63096,0.63096,0.25119,0.11749,0.11749, + 0.11749,0.11749,0.11749,0.11749,0.11749,0.11749,0.11749,0.11749,0.11749,0.11749 + }; +#endif + + int t = 20*tonality2[b]; + if (t > 19) t = 19; + eb2[b] = eb[b] * tab[t]; + } + + + /********************************************************************** + * convolve the partitioned energy and unpredictability + * with the spreading function, s3_l[b][k] + ******************************************************************** */ + { + int kk = 0; + for ( b = 0;b < gfc->npart_l; b++ ) + { + FLOAT8 ecb; + + /**** convolve the partitioned energy with the spreading function ****/ + + ecb = 0; + +#if 1 + for ( k = gfc->s3ind[b][0]; k <= gfc->s3ind[b][1]; k++ ) + { + ecb = mask_add(ecb,gfc->s3_ll[kk++] * eb2[k],k,k-b,gfc); + } + + ecb *= 0.158489319246111; // pow(10,-0.8) +#endif + +#if 0 + for ( k = gfc->s3ind[b][0]; k <= gfc->s3ind[b][1]; k++ ) + { + ecb += gfc->s3_ll[kk++] * eb2[k]; + } + + ecb *= 0.223872113856834; // pow(10,-0.65); +#endif + + /**** long block pre-echo control ****/ + + /* dont use long block pre-echo control if previous granule was + * a short block. This is to avoid the situation: + * frame0: quiet (very low masking) + * frame1: surge (triggers short blocks) + * frame2: regular frame. looks like pre-echo when compared to + * frame0, but all pre-echo was in frame1. + */ + + /* chn=0,1 L and R channels + chn=2,3 S and M channels. + */ + +#define NS_INTERP(x,y,r) (pow((x),(r))*pow((y),1-(r))) + + if (gfc->blocktype_old[chn>1 ? chn-2 : chn] == SHORT_TYPE ) + thr[b] = ecb; /* Min(ecb, rpelev*gfc->nb_1[chn][b]); */ + else + thr[b] = NS_INTERP(Min(ecb, Min(rpelev*gfc->nb_1[chn][b],rpelev2*gfc->nb_2[chn][b])),ecb,pcfact); + + gfc->nb_2[chn][b] = gfc->nb_1[chn][b]; + gfc->nb_1[chn][b] = ecb; + } + } + + /*************************************************************** + * determine the block type (window type) + ***************************************************************/ + + { + static int count=0; + FLOAT en_subshort[12]; + FLOAT attack_intensity[12]; + int ns_uselongblock = 1; + + /* calculate energies of each sub-shortblocks */ + + k = 0; + for(i=0;i<12;i++) + { + en_subshort[i] = 0; + for(j=0;j<576/9;j++) + { + en_subshort[i] += ns_hpfsmpl[chn][k] * ns_hpfsmpl[chn][k]; + k++; + } + + if (en_subshort[i] < 100) en_subshort[i] = 100; + } + + /* compare energies between sub-shortblocks */ + +#define NSATTACKTHRE 150 +#define NSATTACKTHRE_S 300 + + for(i=0;i<2;i++) { + attack_intensity[i] = en_subshort[i] / gfc->nsPsy.last_en_subshort[chn][7+i]; + } + + for(;i<12;i++) { + attack_intensity[i] = en_subshort[i] / en_subshort[i-2]; + } + + ns_attacks[0] = ns_attacks[1] = ns_attacks[2] = ns_attacks[3] = 0; + + for(i=0;i<12;i++) + { + if (!ns_attacks[i/3] && attack_intensity[i] > (chn == 3 ? (gfc->presetTune.use ? gfc->presetTune.attackthre_s : NSATTACKTHRE_S) + : (gfc->presetTune.use ? gfc->presetTune.attackthre : NSATTACKTHRE))) ns_attacks[i/3] = (i % 3)+1; + } + + if (ns_attacks[0] && gfc->nsPsy.last_attacks[chn][2]) ns_attacks[0] = 0; + if (ns_attacks[1] && ns_attacks[0]) ns_attacks[1] = 0; + if (ns_attacks[2] && ns_attacks[1]) ns_attacks[2] = 0; + if (ns_attacks[3] && ns_attacks[2]) ns_attacks[3] = 0; + + if (gfc->nsPsy.last_attacks[chn][2] == 3 || + ns_attacks[0] || ns_attacks[1] || ns_attacks[2] || ns_attacks[3]) ns_uselongblock = 0; + + if (chn < 4) count++; + + for(i=0;i<9;i++) + { + gfc->nsPsy.last_en_subshort[chn][i] = en_subshort[i]; + gfc->nsPsy.last_attack_intensity[chn][i] = attack_intensity[i]; + } + + if (gfp->short_blocks == short_block_dispensed) { + uselongblock[chn] = 1; + } + else if (gfp->short_blocks == short_block_forced) { + uselongblock[chn] = 0; + } + else { + if (chn < 2) { + uselongblock[chn] = ns_uselongblock; + } else { + if (ns_uselongblock == 0) uselongblock[0] = uselongblock[1] = 0; + } + } + } + +#if defined(HAVE_GTK) + if (gfp->analysis) { + FLOAT mn,mx,ma=0,mb=0,mc=0; + + for ( j = HBLKSIZE_s/2; j < HBLKSIZE_s; j ++) + { + ma += gfc->energy_s[0][j]; + mb += gfc->energy_s[1][j]; + mc += gfc->energy_s[2][j]; + } + mn = Min(ma,mb); + mn = Min(mn,mc); + mx = Max(ma,mb); + mx = Max(mx,mc); + + gfc->pinfo->ers[gr_out][chn]=gfc->ers_save[chn]; + gfc->ers_save[chn]=(mx/(1e-12+mn)); + } +#endif + + + /*************************************************************** + * compute masking thresholds for long blocks + ***************************************************************/ + + for ( sb = 0; sb < NBPSY_l; sb++ ) + { + FLOAT8 enn = gfc->w1_l[sb] * eb[gfc->bu_l[sb]] + gfc->w2_l[sb] * eb[gfc->bo_l[sb]]; + FLOAT8 thmm = gfc->w1_l[sb] *thr[gfc->bu_l[sb]] + gfc->w2_l[sb] * thr[gfc->bo_l[sb]]; + + for ( b = gfc->bu_l[sb]+1; b < gfc->bo_l[sb]; b++ ) + { + enn += eb[b]; + thmm += thr[b]; + } + + gfc->en [chn].l[sb] = enn; + gfc->thm[chn].l[sb] = thmm; + } + + + /*************************************************************** + * compute masking thresholds for short blocks + ***************************************************************/ + + for ( sblock = 0; sblock < 3; sblock++ ) + { + j = 0; + for ( b = 0; b < gfc->npart_s_orig; b++ ) + { + FLOAT ecb = gfc->energy_s[sblock][j++]; + for (i = 1 ; inumlines_s[b]; ++i) + { + ecb += gfc->energy_s[sblock][j++]; + } + eb[b] = ecb; + } + + { + int kk = 0; + for ( b = 0; b < gfc->npart_s; b++ ) + { + FLOAT8 ecb = 0; + for ( k = gfc->s3ind_s[b][0]; k <= gfc->s3ind_s[b][1]; k++ ) + { + ecb += gfc->s3_ss[kk++] * eb[k]; + } + +/* 2001-07-13 */ + /* this looks like a BUG */ + thr[b] = Max (1e-6, ecb); + + if (gfp->VBR == vbr_mtrh) { + thr[b] = Min( ecb, rpelev_s * gfc->nb_s1[chn][b] ); + if (gfc->blocktype_old[chn>1 ? chn-2 : chn] == SHORT_TYPE ) { + thr[b] = Min( thr[b], rpelev2_s * gfc->nb_s2[chn][b] ); + } + thr[b] = Max( thr[b], 1e-37 ); + gfc->nb_s2[chn][b] = gfc->nb_s1[chn][b]; + gfc->nb_s1[chn][b] = ecb; + } + } + } + for ( sb = 0; sb < NBPSY_s; sb++ ) + { + FLOAT8 enn = gfc->w1_s[sb] * eb[gfc->bu_s[sb]] + gfc->w2_s[sb] * eb[gfc->bo_s[sb]]; + FLOAT8 thmm = gfc->w1_s[sb] *thr[gfc->bu_s[sb]] + gfc->w2_s[sb] * thr[gfc->bo_s[sb]]; + + for ( b = gfc->bu_s[sb]+1; b < gfc->bo_s[sb]; b++ ) + { + enn += eb[b]; + thmm += thr[b]; + } + + /**** short block pre-echo control ****/ + +#define NS_PREECHO_ATT0 0.8 +#define NS_PREECHO_ATT1 0.6 +#define NS_PREECHO_ATT2 0.3 + + thmm *= NS_PREECHO_ATT0; + + if (ns_attacks[sblock] >= 2) { + if (sblock != 0) { + double p = NS_INTERP(gfc->thm[chn].s[sb][sblock-1],thmm,NS_PREECHO_ATT1*pcfact); + thmm = Min(thmm,p); + } else { + double p = NS_INTERP(gfc->nsPsy.last_thm[chn][sb][2],thmm,NS_PREECHO_ATT1*pcfact); + thmm = Min(thmm,p); + } + } else if (ns_attacks[sblock+1] == 1) { + if (sblock != 0) { + double p = NS_INTERP(gfc->thm[chn].s[sb][sblock-1],thmm,NS_PREECHO_ATT1*pcfact); + thmm = Min(thmm,p); + } else { + double p = NS_INTERP(gfc->nsPsy.last_thm[chn][sb][2],thmm,NS_PREECHO_ATT1*pcfact); + thmm = Min(thmm,p); + } + } + + if (ns_attacks[sblock] == 1) { + double p = sblock == 0 ? gfc->nsPsy.last_thm[chn][sb][2] : gfc->thm[chn].s[sb][sblock-1]; + p = NS_INTERP(p,thmm,NS_PREECHO_ATT2*pcfact); + thmm = Min(thmm,p); + } else if ((sblock != 0 && ns_attacks[sblock-1] == 3) || + (sblock == 0 && gfc->nsPsy.last_attacks[chn][2] == 3)) { + double p = sblock <= 1 ? gfc->nsPsy.last_thm[chn][sb][sblock+1] : gfc->thm[chn].s[sb][0]; + p = NS_INTERP(p,thmm,NS_PREECHO_ATT2*pcfact); + thmm = Min(thmm,p); + } + + gfc->en [chn].s[sb][sblock] = enn; + gfc->thm[chn].s[sb][sblock] = thmm; + } + } + + + /*************************************************************** + * save some values for analysis of the next granule + ***************************************************************/ + + for ( sblock = 0; sblock < 3; sblock++ ) + { + for ( sb = 0; sb < NBPSY_s; sb++ ) + { + gfc->nsPsy.last_thm[chn][sb][sblock] = gfc->thm[chn].s[sb][sblock]; + } + } + + for(i=0;i<3;i++) + gfc->nsPsy.last_attacks[chn][i] = ns_attacks[i]; + + } /* end loop over chn */ + + + + /*************************************************************** + * compute M/S thresholds + ***************************************************************/ + + /* from Johnston & Ferreira 1992 ICASSP paper */ + + if ( numchn==4 /* mid/side and r/l */) { + FLOAT8 rside,rmid,mld; + int chmid=2,chside=3; + + for ( sb = 0; sb < NBPSY_l; sb++ ) { + /* use this fix if L & R masking differs by 2db or less */ + /* if db = 10*log10(x2/x1) < 2 */ + /* if (x2 < 1.58*x1) { */ + if (gfc->thm[0].l[sb] <= 1.58*gfc->thm[1].l[sb] + && gfc->thm[1].l[sb] <= 1.58*gfc->thm[0].l[sb]) { + + mld = gfc->mld_l[sb]*gfc->en[chside].l[sb]; + rmid = Max(gfc->thm[chmid].l[sb], Min(gfc->thm[chside].l[sb],mld)); + + mld = gfc->mld_l[sb]*gfc->en[chmid].l[sb]; + rside = Max(gfc->thm[chside].l[sb],Min(gfc->thm[chmid].l[sb],mld)); + + gfc->thm[chmid].l[sb]=rmid; + gfc->thm[chside].l[sb]=rside; + } + } + for ( sb = 0; sb < NBPSY_s; sb++ ) { + for ( sblock = 0; sblock < 3; sblock++ ) { + if (gfc->thm[0].s[sb][sblock] <= 1.58*gfc->thm[1].s[sb][sblock] + && gfc->thm[1].s[sb][sblock] <= 1.58*gfc->thm[0].s[sb][sblock]) { + + mld = gfc->mld_s[sb]*gfc->en[chside].s[sb][sblock]; + rmid = Max(gfc->thm[chmid].s[sb][sblock],Min(gfc->thm[chside].s[sb][sblock],mld)); + + mld = gfc->mld_s[sb]*gfc->en[chmid].s[sb][sblock]; + rside = Max(gfc->thm[chside].s[sb][sblock],Min(gfc->thm[chmid].s[sb][sblock],mld)); + + gfc->thm[chmid].s[sb][sblock]=rmid; + gfc->thm[chside].s[sb][sblock]=rside; + } + } + } + } + + + /* Naoki Shibata 2000 */ + +#define NS_MSFIX 3.5 + + if (numchn == 4) { + FLOAT msfix = NS_MSFIX; + if (gfc->nsPsy.safejoint) msfix = 1; + if (gfp->msfix) msfix = gfp->msfix; + + if (gfc->presetTune.use && gfc->ATH->adjust >= + gfc->presetTune.athadjust_switch_level && + gfc->presetTune.athadjust_msfix > 0) + msfix = gfc->presetTune.athadjust_msfix; + + for ( sb = 0; sb < NBPSY_l; sb++ ) + { + FLOAT8 thmL,thmR,thmM,thmS,ath; + ath = (gfc->ATH->cb[(gfc->bu_l[sb] + gfc->bo_l[sb])/2])*pow(10,-gfp->ATHlower/10.0); + thmL = Max(gfc->thm[0].l[sb],ath); + thmR = Max(gfc->thm[1].l[sb],ath); + thmM = Max(gfc->thm[2].l[sb],ath); + thmS = Max(gfc->thm[3].l[sb],ath); + + if (thmL*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmL * (gfc->presetTune.use ? gfc->presetTune.ms_maskadjust : msfix) / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + if (thmR*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmR * (gfc->presetTune.use ? gfc->presetTune.ms_maskadjust : msfix) / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + + gfc->thm[2].l[sb] = Min(thmM,gfc->thm[2].l[sb]); + gfc->thm[3].l[sb] = Min(thmS,gfc->thm[3].l[sb]); + } + + for ( sb = 0; sb < NBPSY_s; sb++ ) { + for ( sblock = 0; sblock < 3; sblock++ ) { + FLOAT8 thmL,thmR,thmM,thmS,ath; + ath = (gfc->ATH->cb[(gfc->bu_s[sb] + gfc->bo_s[sb])/2])*pow(10,-gfp->ATHlower/10.0); + thmL = Max(gfc->thm[0].s[sb][sblock],ath); + thmR = Max(gfc->thm[1].s[sb][sblock],ath); + thmM = Max(gfc->thm[2].s[sb][sblock],ath); + thmS = Max(gfc->thm[3].s[sb][sblock],ath); + + if (thmL*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmL*msfix / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + if (thmR*msfix < (thmM+thmS)/2) { + FLOAT8 f = thmR*msfix / ((thmM+thmS)/2); + thmM *= f; + thmS *= f; + } + + gfc->thm[2].s[sb][sblock] = Min(gfc->thm[2].s[sb][sblock],thmM); + gfc->thm[3].s[sb][sblock] = Min(gfc->thm[3].s[sb][sblock],thmS); + } + } + } + + ms_ratio_l = 0; + ms_ratio_s = 0; + + + /*************************************************************** + * compute estimation of the amount of bit used in the granule + ***************************************************************/ + + for(chn=0;chnthm[chn].l[sb]*gfc->masking_lower != 0 && + gfc->en[chn].l[sb]/(gfc->thm[chn].l[sb]*gfc->masking_lower) > 1) + t = log(gfc->en[chn].l[sb]/(gfc->thm[chn].l[sb]*gfc->masking_lower)); + else + t = 0; + msum += regcoef[sb+1] * t; + } + + gfc->nsPsy.pe_l[chn] = msum; + } + + { + static FLOAT8 regcoef[] = { + 1236.28,0,0,0,0.434542,25.0738,0,0,0,19.5442,19.7486,60,100,0 + }; + + FLOAT8 msum = regcoef[0]/4; + int sb,sblock; + + for(sblock=0;sblock<3;sblock++) + { + for ( sb = 0; sb < NBPSY_s; sb++ ) + { + FLOAT8 t; + + if (gfc->thm[chn].s[sb][sblock] * gfc->masking_lower != 0 && + gfc->en[chn].s[sb][sblock] / (gfc->thm[chn].s[sb][sblock] * gfc->masking_lower) > 1) + t = log(gfc->en[chn].s[sb][sblock] / (gfc->thm[chn].s[sb][sblock] * gfc->masking_lower)); + else + t = 0; + msum += regcoef[sb+1] * t; + } + } + + gfc->nsPsy.pe_s[chn] = msum; + } + + //gfc->pe[chn] -= 150; + } + + /*************************************************************** + * determine final block type + ***************************************************************/ + + for (chn=0; chnchannels_out; chn++) { + blocktype[chn] = NORM_TYPE; + } + + if (gfp->short_blocks == short_block_coupled) { + /* force both channels to use the same block type */ + /* this is necessary if the frame is to be encoded in ms_stereo. */ + /* But even without ms_stereo, FhG does this */ + int bothlong= (uselongblock[0] && uselongblock[1]); + if (!bothlong) { + uselongblock[0]=0; + uselongblock[1]=0; + } + } + + /* update the blocktype of the previous granule, since it depends on what + * happend in this granule */ + for (chn=0; chnchannels_out; chn++) { + if ( uselongblock[chn]) + { /* no attack : use long blocks */ + assert( gfc->blocktype_old[chn] != START_TYPE ); + switch( gfc->blocktype_old[chn] ) + { + case NORM_TYPE: + case STOP_TYPE: + blocktype[chn] = NORM_TYPE; + break; + case SHORT_TYPE: + blocktype[chn] = STOP_TYPE; + break; + } + } else { + /* attack : use short blocks */ + blocktype[chn] = SHORT_TYPE; + if ( gfc->blocktype_old[chn] == NORM_TYPE ) { + gfc->blocktype_old[chn] = START_TYPE; + } + if ( gfc->blocktype_old[chn] == STOP_TYPE ) { + gfc->blocktype_old[chn] = SHORT_TYPE ; + } + } + + blocktype_d[chn] = gfc->blocktype_old[chn]; /* value returned to calling program */ + gfc->blocktype_old[chn] = blocktype[chn]; /* save for next call to l3psy_anal */ + + if (gfc->presetTune.use) { + if (blocktype_d[chn] != NORM_TYPE) + gfc->presetTune.quantcomp_current = gfc->presetTune.quantcomp_type_s; + else + gfc->presetTune.quantcomp_current = gfp->experimentalX; + + if (gfc->ATH->adjust >= gfc->presetTune.athadjust_switch_level && + blocktype_d[chn] == NORM_TYPE && + gfc->presetTune.quantcomp_alt_type > -1) { + gfc->presetTune.quantcomp_current = gfc->presetTune.quantcomp_alt_type; + } + } + } + + /********************************************************************* + * compute the value of PE to return (one granule delay) + *********************************************************************/ + for(chn=0;chnanalysis) gfc->pinfo->pe[gr_out][chn] = percep_entropy[chn]; + } else { + if (blocktype_d[0] == SHORT_TYPE) { + percep_MS_entropy[chn-2] = pe_s[chn]; + } else { + percep_MS_entropy[chn-2] = pe_l[chn]; + } + if (gfp->analysis) gfc->pinfo->pe[gr_out][chn] = percep_MS_entropy[chn-2]; + } + } + + return 0; +} + + + + + +/* + * The spreading function. Values returned in units of energy + */ +FLOAT8 s3_func(FLOAT8 bark) { + + FLOAT8 tempx,x,tempy,temp; + tempx = bark; + if (tempx>=0) tempx *= 3; + else tempx *=1.5; + + if(tempx>=0.5 && tempx<=2.5) + { + temp = tempx - 0.5; + x = 8.0 * (temp*temp - 2.0 * temp); + } + else x = 0.0; + tempx += 0.474; + tempy = 15.811389 + 7.5*tempx - 17.5*sqrt(1.0+tempx*tempx); + + if (tempy <= -60.0) return 0.0; + + tempx = exp( (x + tempy)*LN_TO_LOG10 ); + + /* Normalization. The spreading function should be normalized so that: + +inf + / + | s3 [ bark ] d(bark) = 1 + / + -inf + */ + tempx /= .6609193; + return tempx; + +} + + + + + + + + +int L3para_read(lame_global_flags * gfp, FLOAT8 sfreq, int *numlines_l,int *numlines_s, +FLOAT8 *minval, +FLOAT8 s3_l[CBANDS][CBANDS], FLOAT8 s3_s[CBANDS][CBANDS], +FLOAT8 *SNR, +int *bu_l, int *bo_l, FLOAT8 *w1_l, FLOAT8 *w2_l, +int *bu_s, int *bo_s, FLOAT8 *w1_s, FLOAT8 *w2_s, +int *npart_l_orig,int *npart_l,int *npart_s_orig,int *npart_s) +{ + lame_internal_flags *gfc=gfp->internal_flags; + + + FLOAT8 bval_l[CBANDS], bval_s[CBANDS]; + FLOAT8 bval_l_width[CBANDS], bval_s_width[CBANDS]; + int i,j; + int partition[HBLKSIZE]; + + + + /* compute numlines, the number of spectral lines in each partition band */ + /* each partition band should be about DELBARK wide. */ + j=0; + for(i=0;i= j so that (bark - bark_l[i-1]) < DELBARK */ + ji = j; + bark1 = freq2bark(sfreq*ji/BLKSIZE); + + ++j2; + ji = j2; + bark2 = freq2bark(sfreq*ji/BLKSIZE); + } while ((bark2 - bark1) < DELBARK && j2<=BLKSIZE/2); + + for (k=j; k BLKSIZE/2) break; + } + *npart_l_orig = i+1; + assert(*npart_l_orig <= CBANDS); + + /* compute which partition bands are in which scalefactor bands */ + { int i1,i2,sfb,start,end; + FLOAT8 freq1,freq2; + for ( sfb = 0; sfb < SBMAX_l; sfb++ ) { + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + freq1 = sfreq*(start-.5)/(2*576); + freq2 = sfreq*(end-1+.5)/(2*576); + + i1 = floor(.5 + BLKSIZE*freq1/sfreq); + if (i1<0) i1=0; + i2 = floor(.5 + BLKSIZE*freq2/sfreq); + if (i2>BLKSIZE/2) i2=BLKSIZE/2; + + // DEBUGF(gfc,"longblock: old: (%i,%i) new: (%i,%i) %i %i \n",bu_l[sfb],bo_l[sfb],partition[i1],partition[i2],i1,i2); + + w1_l[sfb]=.5; + w2_l[sfb]=.5; + bu_l[sfb]=partition[i1]; + bo_l[sfb]=partition[i2]; + + } + } + + + /* compute bark value and ATH of each critical band */ + j = 0; + for ( i = 0; i < *npart_l_orig; i++ ) { + int k; + FLOAT8 bark1,bark2; + /* FLOAT8 mval,freq; */ + + // Calculating the medium bark scaled frequency of the spectral lines + // from j ... j + numlines[i]-1 (=spectral lines in parition band i) + + k = numlines_l[i] - 1; + bark1 = freq2bark(sfreq*(j+0)/BLKSIZE); + bark2 = freq2bark(sfreq*(j+k)/BLKSIZE); + bval_l[i] = .5*(bark1+bark2); + + bark1 = freq2bark(sfreq*(j+0-.5)/BLKSIZE); + bark2 = freq2bark(sfreq*(j+k+.5)/BLKSIZE); + bval_l_width[i] = bark2-bark1; + + gfc->ATH->cb [i] = 1.e37; // preinit for minimum search + for (k=0; k < numlines_l[i]; k++, j++) { + FLOAT8 freq = sfreq*j/(1000.0*BLKSIZE); + FLOAT8 level; + assert( freq <= 24 ); // or only '<' + // freq = Min(.1,freq); // ATH below 100 Hz constant, not further climbing + level = ATHformula (freq*1000, gfp) - 20; // scale to FFT units; returned value is in dB + level = pow ( 10., 0.1*level ); // convert from dB -> energy + level *= numlines_l [i]; + if ( level < gfc->ATH->cb [i] ) + gfc->ATH->cb [i] = level; + } + + + } + + /* MINVAL. For low freq, the strength of the masking is limited by minval + * this is an ISO MPEG1 thing, dont know if it is really needed */ + for(i=0;i<*npart_l_orig;i++){ + double x = (-20+bval_l[i]*20.0/10.0); + if (bval_l[i]>10) x = 0; + minval[i]=pow(10.0,x/10); + gfc->PSY->prvTonRed[i] = minval[i]; + } + + + + + + + + /************************************************************************/ + /* SHORT BLOCKS */ + /************************************************************************/ + + /* compute numlines */ + j=0; + for(i=0;i= j so that (bark - bark_s[i-1]) < DELBARK */ + ji = j; + bark1 = freq2bark(sfreq*ji/BLKSIZE_s); + + ++j2; + ji = j2; + bark2 = freq2bark(sfreq*ji/BLKSIZE_s); + + } while ((bark2 - bark1) < DELBARK && j2<=BLKSIZE_s/2); + + for (k=j; k BLKSIZE_s/2) break; + } + *npart_s_orig = i+1; + assert(*npart_s_orig <= CBANDS); + + /* compute which partition bands are in which scalefactor bands */ + { int i1,i2,sfb,start,end; + FLOAT8 freq1,freq2; + for ( sfb = 0; sfb < SBMAX_s; sfb++ ) { + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb+1 ]; + freq1 = sfreq*(start-.5)/(2*192); + freq2 = sfreq*(end-1+.5)/(2*192); + + i1 = floor(.5 + BLKSIZE_s*freq1/sfreq); + if (i1<0) i1=0; + i2 = floor(.5 + BLKSIZE_s*freq2/sfreq); + if (i2>BLKSIZE_s/2) i2=BLKSIZE_s/2; + + //DEBUGF(gfc,"shortblock: old: (%i,%i) new: (%i,%i) %i %i \n",bu_s[sfb],bo_s[sfb], partition[i1],partition[i2],i1,i2); + + w1_s[sfb]=.5; + w2_s[sfb]=.5; + bu_s[sfb]=partition[i1]; + bo_s[sfb]=partition[i2]; + + } + } + + + + + + /* compute bark values of each critical band */ + j = 0; + for(i=0;i<*npart_s_orig;i++) + { + int k; + FLOAT8 bark1,bark2,snr; + k = numlines_s[i] - 1; + + bark1 = freq2bark (sfreq*(j+0)/BLKSIZE_s); + bark2 = freq2bark (sfreq*(j+k)/BLKSIZE_s); + bval_s[i] = .5*(bark1+bark2); + + bark1 = freq2bark (sfreq*(j+0-.5)/BLKSIZE_s); + bark2 = freq2bark (sfreq*(j+k+.5)/BLKSIZE_s); + bval_s_width[i] = bark2-bark1; + j += k+1; + + /* SNR formula */ + if (bval_s[i]<13) + snr=-8.25; + else + snr = -4.5 * (bval_s[i]-13)/(24.0-13.0) + + -8.25*(bval_s[i]-24)/(13.0-24.0); + + SNR[i]=pow(10.0,snr/10.0); + } + + + + + + + /************************************************************************ + * Now compute the spreading function, s[j][i], the value of the spread-* + * ing function, centered at band j, for band i, store for later use * + ************************************************************************/ + /* i.e.: sum over j to spread into signal barkval=i + NOTE: i and j are used opposite as in the ISO docs */ + for(i=0;i<*npart_l_orig;i++) { + for(j=0;j<*npart_l_orig;j++) { + s3_l[i][j]=s3_func(bval_l[i]-bval_l[j])*bval_l_width[j]; + } + } + for(i=0;i<*npart_s_orig;i++) { + for(j=0;j<*npart_s_orig;j++) { + s3_s[i][j]=s3_func(bval_s[i]-bval_s[j])*bval_s_width[j]; + } + } + + + + + /* compute: */ + /* npart_l_orig = number of partition bands before convolution */ + /* npart_l = number of partition bands after convolution */ + + *npart_l=bo_l[NBPSY_l-1]+1; + *npart_s=bo_s[NBPSY_s-1]+1; + + assert(*npart_l <= *npart_l_orig); + assert(*npart_s <= *npart_s_orig); + + + /* setup stereo demasking thresholds */ + /* formula reverse enginerred from plot in paper */ + for ( i = 0; i < NBPSY_s; i++ ) { + FLOAT8 arg,mld; + arg = freq2bark(sfreq*gfc->scalefac_band.s[i]/(2*192)); + arg = (Min(arg, 15.5)/15.5); + + mld = 1.25*(1-cos(PI*arg))-2.5; + gfc->mld_s[i] = pow(10.0,mld); + } + for ( i = 0; i < NBPSY_l; i++ ) { + FLOAT8 arg,mld; + arg = freq2bark(sfreq*gfc->scalefac_band.l[i]/(2*576)); + arg = (Min(arg, 15.5)/15.5); + + mld = 1.25*(1-cos(PI*arg))-2.5; + gfc->mld_l[i] = pow(10.0,mld); + } + +#define temporalmask_sustain_sec 0.01 + + /* setup temporal masking */ + gfc->decay = exp(-1.0*LOG10/(temporalmask_sustain_sec*sfreq/192.0)); + + return 0; +} + + + + + + + + + + + +int psymodel_init(lame_global_flags *gfp) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int i,j,b,sb,k,samplerate; + + FLOAT8 s3_s[CBANDS][CBANDS]; + FLOAT8 s3_l[CBANDS][CBANDS]; + int numberOfNoneZero; + + samplerate = gfp->out_samplerate; + gfc->ms_ener_ratio_old=.25; + gfc->blocktype_old[0]=STOP_TYPE; + gfc->blocktype_old[1]=STOP_TYPE; + gfc->blocktype_old[0]=SHORT_TYPE; + gfc->blocktype_old[1]=SHORT_TYPE; + + for (i=0; i<4; ++i) { + for (j=0; jnb_1[i][j]=1e20; + gfc->nb_2[i][j]=1e20; + } + for ( sb = 0; sb < NBPSY_l; sb++ ) { + gfc->en[i].l[sb] = 1e20; + gfc->thm[i].l[sb] = 1e20; + } + for (j=0; j<3; ++j) { + for ( sb = 0; sb < NBPSY_s; sb++ ) { + gfc->en[i].s[sb][j] = 1e20; + gfc->thm[i].s[sb][j] = 1e20; + } + } + } + for (i=0; i<4; ++i) { + for (j=0; j<3; ++j) { + for ( sb = 0; sb < NBPSY_s; sb++ ) { + gfc->nsPsy.last_thm[i][sb][j] = 1e20; + } + } + } + for(i=0;i<4;i++) { + for(j=0;j<9;j++) + gfc->nsPsy.last_en_subshort[i][j] = 100; + for(j=0;j<3;j++) + gfc->nsPsy.last_attacks[i][j] = 0; + gfc->nsPsy.pe_l[i] = gfc->nsPsy.pe_s[i] = 0; + } + + + + + /* gfp->cwlimit = sfreq*j/1024.0; */ + gfc->cw_lower_index=6; + gfc->cw_upper_index = gfc->PSY->cwlimit*1024.0/gfp->out_samplerate; + gfc->cw_upper_index=Min(HBLKSIZE-4,gfc->cw_upper_index); /* j+3 < HBLKSIZE-1 */ + gfc->cw_upper_index=Max(6,gfc->cw_upper_index); + + for ( j = 0; j < HBLKSIZE; j++ ) + gfc->cw[j] = 0.4f; + + + + i=L3para_read( gfp,(FLOAT8) samplerate,gfc->numlines_l,gfc->numlines_s, + gfc->minval,s3_l,s3_s,gfc->SNR_s,gfc->bu_l, + gfc->bo_l,gfc->w1_l,gfc->w2_l, gfc->bu_s,gfc->bo_s, + gfc->w1_s,gfc->w2_s,&gfc->npart_l_orig,&gfc->npart_l, + &gfc->npart_s_orig,&gfc->npart_s ); + if (i!=0) return -1; + + + + /* npart_l_orig = number of partition bands before convolution */ + /* npart_l = number of partition bands after convolution */ + + numberOfNoneZero = 0; + for (i=0; inpart_l; i++) { + for (j = 0; j < gfc->npart_l_orig; j++) { + if (s3_l[i][j] != 0.0) + break; + } + gfc->s3ind[i][0] = j; + + for (j = gfc->npart_l_orig - 1; j > 0; j--) { + if (s3_l[i][j] != 0.0) + break; + } + gfc->s3ind[i][1] = j; + numberOfNoneZero += (gfc->s3ind[i][1] - gfc->s3ind[i][0] + 1); + } + gfc->s3_ll = malloc(sizeof(FLOAT8)*numberOfNoneZero); + if (!gfc->s3_ll) + return -1; + + k = 0; + for (i=0; inpart_l; i++) { + for (j = gfc->s3ind[i][0]; j <= gfc->s3ind[i][1]; j++) { + gfc->s3_ll[k++] = s3_l[i][j]; + } + } + + + + numberOfNoneZero = 0; + for (i=0; inpart_s; i++) { + for (j = 0; j < gfc->npart_s_orig; j++) { + if (s3_s[i][j] != 0.0) + break; + } + gfc->s3ind_s[i][0] = j; + + for (j = gfc->npart_s_orig - 1; j > 0; j--) { + if (s3_s[i][j] != 0.0) + break; + } + gfc->s3ind_s[i][1] = j; + numberOfNoneZero += (gfc->s3ind_s[i][1] - gfc->s3ind_s[i][0] + 1); + } + gfc->s3_ss = malloc(sizeof(FLOAT8)*numberOfNoneZero); + if (!gfc->s3_ss) + return -1; + + + + + /* + #include "debugscalefac.c" + */ + + + + if (gfc->nsPsy.use) { + /* long block spreading function normalization */ + for ( b = 0;b < gfc->npart_l; b++ ) { + for ( k = gfc->s3ind[b][0]; k <= gfc->s3ind[b][1]; k++ ) { + // spreading function has been properly normalized by + // multiplying by DELBARK/.6609193 = .515. + // It looks like Naoki was + // way ahead of me and added this factor here! + // it is no longer needed. + //gfc->s3_l[b][k] *= 0.5; + } + } + /* short block spreading function normalization */ + // no longer needs to be normalized, but nspsytune wants + // SNR_s applied here istead of later to save CPU cycles + for ( b = 0;b < gfc->npart_s; b++ ) { + FLOAT8 norm=0; + for ( k = gfc->s3ind_s[b][0]; k <= gfc->s3ind_s[b][1]; k++ ) { + norm += s3_s[b][k]; + } + for ( k = gfc->s3ind_s[b][0]; k <= gfc->s3ind_s[b][1]; k++ ) { + s3_s[b][k] *= gfc->SNR_s[b] /* / norm */; + } + } + } + + + + if (gfc->nsPsy.use) { +#if 1 + /* spread only from npart_l bands. Normally, we use the spreading + * function to convolve from npart_l_orig down to npart_l bands + */ + for(b=0;bnpart_l;b++) + if (gfc->s3ind[b][1] > gfc->npart_l-1) gfc->s3ind[b][1] = gfc->npart_l-1; +#endif + } + k = 0; + for (i=0; inpart_s; i++) { + for (j = gfc->s3ind_s[i][0]; j <= gfc->s3ind_s[i][1]; j++) { + gfc->s3_ss[k++] = s3_s[i][j]; + } + } + + + + /* init. for loudness approx. -jd 2001 mar 27*/ + gfc->loudness_sq_save[0] = 0.0; + gfc->loudness_sq_save[1] = 0.0; + + + + return 0; +} + + + + + +/* psycho_loudness_approx + jd - 2001 mar 12 +in: energy - BLKSIZE/2 elements of frequency magnitudes ^ 2 + gfp - uses out_samplerate, ATHtype (also needed for ATHformula) +returns: loudness^2 approximation, a positive value roughly tuned for a value + of 1.0 for signals near clipping. +notes: When calibrated, feeding this function binary white noise at sample + values +32767 or -32768 should return values that approach 3. + ATHformula is used to approximate an equal loudness curve. +future: Data indicates that the shape of the equal loudness curve varies + with intensity. This function might be improved by using an equal + loudness curve shaped for typical playback levels (instead of the + ATH, that is shaped for the threshold). A flexible realization might + simply bend the existing ATH curve to achieve the desired shape. + However, the potential gain may not be enough to justify an effort. +*/ +FLOAT +psycho_loudness_approx( FLOAT *energy, lame_global_flags *gfp ) +{ + int i; + static int eql_type = -1; + static FLOAT eql_w[BLKSIZE/2];/* equal loudness weights (based on ATH) */ + const FLOAT vo_scale= 1./( 14752 ); /* tuned for output level */ + /* (sensitive to energy scale) */ + FLOAT loudness_power; + + if( eql_type != gfp->ATHtype ) { + /* compute equal loudness weights (eql_w) */ + FLOAT freq; + FLOAT freq_inc = gfp->out_samplerate / (BLKSIZE); + FLOAT eql_balance = 0.0; + eql_type = gfp->ATHtype; + freq = 0.0; + for( i = 0; i < BLKSIZE/2; ++i ) { + freq += freq_inc; + /* convert ATH dB to relative power (not dB) */ + /* to determine eql_w */ + eql_w[i] = 1. / pow( 10, ATHformula( freq, gfp ) / 10 ); + eql_balance += eql_w[i]; + } + eql_balance = 1 / eql_balance; + for( i = BLKSIZE/2; --i >= 0; ) { /* scale weights */ + eql_w[i] *= eql_balance; + } + } + + loudness_power = 0.0; + for( i = 0; i < BLKSIZE/2; ++i ) { /* apply weights to power in freq. bands*/ + loudness_power += energy[i] * eql_w[i]; + } + loudness_power /= (BLKSIZE/2); + loudness_power *= vo_scale * vo_scale; + + return( loudness_power ); +} diff --git a/lib/lame/psymodel.h b/lib/lame/psymodel.h new file mode 100644 index 0000000..e1c267c --- /dev/null +++ b/lib/lame/psymodel.h @@ -0,0 +1,49 @@ +/* + * psymodel.h + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_PSYMODEL_H +#define LAME_PSYMODEL_H + +#include "l3side.h" + +int L3psycho_anal( lame_global_flags *gfc, + const sample_t *buffer[2], int gr, + FLOAT8 *ms_ratio, + FLOAT8 *ms_ratio_next, + III_psy_ratio ratio[2][2], + III_psy_ratio MS_ratio[2][2], + FLOAT8 pe[2], FLOAT8 pe_MS[2], FLOAT8 ener[2], + int blocktype_d[2]); + +int L3psycho_anal_ns( lame_global_flags *gfc, + const sample_t *buffer[2], int gr, + FLOAT8 *ms_ratio, + FLOAT8 *ms_ratio_next, + III_psy_ratio ratio[2][2], + III_psy_ratio MS_ratio[2][2], + FLOAT8 pe[2], FLOAT8 pe_MS[2], FLOAT8 ener[2], + int blocktype_d[2]); + + +int psymodel_init(lame_global_flags *gfp); + + +#endif /* LAME_PSYMODEL_H */ diff --git a/lib/lame/quantize.c b/lib/lame/quantize.c new file mode 100644 index 0000000..0095bb7 --- /dev/null +++ b/lib/lame/quantize.c @@ -0,0 +1,1776 @@ +/* + * MP3 quantization + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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: quantize.c,v 1.1 2002/04/28 17:30:24 kramm Exp $ */ + +#include "config_static.h" + +#include +#include +#include "util.h" +#include "l3side.h" +#include "quantize.h" +#include "reservoir.h" +#include "quantize_pvt.h" +#include "lame-analysis.h" +#include "vbrquantize.h" + +#ifdef WITH_DMALLOC +#include +#endif + + +/************************************************************************ + * + * init_outer_loop() + * mt 6/99 + * + * initializes cod_info, scalefac and xrpow + * + * returns 0 if all energies in xr are zero, else 1 + * + ************************************************************************/ + +static int +init_outer_loop( + lame_internal_flags *gfc, + gr_info *const cod_info, + III_scalefac_t *const scalefac, + const FLOAT8 xr[576], + FLOAT8 xrpow[576] ) +{ + FLOAT8 tmp, sum = 0; + int i; + + /* initialize fresh cod_info + */ + cod_info->part2_3_length = 0; + cod_info->big_values = 0; + cod_info->count1 = 0; + cod_info->global_gain = 210; + cod_info->scalefac_compress = 0; + /* window_switching_flag was set in psymodel.c? */ + /* block_type was set in psymodel.c? */ + /* mixed_block_flag would be set in ^ */ + cod_info->table_select [0] = 0; + cod_info->table_select [1] = 0; + cod_info->table_select [2] = 0; + cod_info->subblock_gain[0] = 0; + cod_info->subblock_gain[1] = 0; + cod_info->subblock_gain[2] = 0; + cod_info->region0_count = 0; + cod_info->region1_count = 0; + cod_info->preflag = 0; + cod_info->scalefac_scale = 0; + cod_info->count1table_select = 0; + cod_info->part2_length = 0; + if (cod_info->block_type == SHORT_TYPE) { + cod_info->sfb_lmax = 0; + cod_info->sfb_smin = 0; + if (cod_info->mixed_block_flag) { + /* + * MPEG-1: sfbs 0-7 long block, 3-12 short blocks + * MPEG-2(.5): sfbs 0-5 long block, 3-12 short blocks + */ + cod_info->sfb_lmax = gfc->is_mpeg1 ? 8 : 6; + cod_info->sfb_smin = 3; + } + } else { + cod_info->sfb_lmax = SBPSY_l; + cod_info->sfb_smin = SBPSY_s; + } + cod_info->count1bits = 0; + cod_info->sfb_partition_table = nr_of_sfb_block[0][0]; + cod_info->slen[0] = 0; + cod_info->slen[1] = 0; + cod_info->slen[2] = 0; + cod_info->slen[3] = 0; + + /* fresh scalefactors are all zero + */ + memset(scalefac, 0, sizeof(III_scalefac_t)); + memset(&gfc->pseudohalf, 0, sizeof(gfc->pseudohalf)); + + /* check if there is some energy we have to quantize + * and calculate xrpow matching our fresh scalefactors + */ + for (i = 0; i < 576; ++i) { + tmp = fabs (xr[i]); + sum += tmp; + xrpow[i] = sqrt (tmp * sqrt(tmp)); + } + /* return 1 if we have something to quantize, else 0 + */ + return sum > (FLOAT8)1E-20; +} + + + +/************************************************************************ + * + * bin_search_StepSize() + * + * author/date?? + * + * binary step size search + * used by outer_loop to get a quantizer step size to start with + * + ************************************************************************/ + +typedef enum { + BINSEARCH_NONE, + BINSEARCH_UP, + BINSEARCH_DOWN +} binsearchDirection_t; + +int +bin_search_StepSize( + lame_internal_flags * const gfc, + gr_info * const cod_info, + const int desired_rate, + const int start, + const FLOAT8 xrpow [576], + int l3enc [576] ) +{ + int nBits; + int CurrentStep; + int flag_GoneOver = 0; + int StepSize = start; + + binsearchDirection_t Direction = BINSEARCH_NONE; + assert(gfc->CurrentStep); + CurrentStep = gfc->CurrentStep; + + do { + cod_info->global_gain = StepSize; + nBits = count_bits(gfc,l3enc,xrpow,cod_info); + + if (CurrentStep == 1) break; /* nothing to adjust anymore */ + + if (flag_GoneOver) CurrentStep /= 2; + + if (nBits > desired_rate) { + /* increase Quantize_StepSize */ + if (Direction == BINSEARCH_DOWN && !flag_GoneOver) { + flag_GoneOver = 1; + CurrentStep /= 2; /* late adjust */ + } + Direction = BINSEARCH_UP; + StepSize += CurrentStep; + if (StepSize > 255) break; + } + else if (nBits < desired_rate) { + /* decrease Quantize_StepSize */ + if (Direction == BINSEARCH_UP && !flag_GoneOver) { + flag_GoneOver = 1; + CurrentStep /= 2; /* late adjust */ + } + Direction = BINSEARCH_DOWN; + StepSize -= CurrentStep; + if (StepSize < 0) break; + } + else break; /* nBits == desired_rate;; most unlikely to happen.*/ + } while (1); /* For-ever, break is adjusted. */ + + CurrentStep = start - StepSize; + + gfc->CurrentStep = CurrentStep/4 != 0 ? 4 : 2; + + return nBits; +} + + + + +/*************************************************************************** + * + * inner_loop () + * + * author/date?? + * + * The code selects the best global gain for a particular set of scalefacs + * + ***************************************************************************/ + +int +inner_loop( + lame_internal_flags * const gfc, + gr_info * const cod_info, + const int max_bits, + const FLOAT8 xrpow [576], + int l3enc [576] ) +{ + int bits; + + assert(max_bits >= 0); + + /* scalefactors may have changed, so count bits + */ + bits=count_bits(gfc,l3enc,xrpow,cod_info); + + /* increase quantizer stepsize until needed bits are below maximum + */ + while (bits > max_bits) { + cod_info->global_gain++; + bits = count_bits (gfc, l3enc, xrpow, cod_info); + } + + return bits; +} + + + +/************************************************************************* + * + * loop_break() + * + * author/date?? + * + * Function: Returns zero if there is a scalefac which has not been + * amplified. Otherwise it returns one. + * + *************************************************************************/ + +inline +static int +loop_break( + const gr_info * const cod_info, + const III_scalefac_t * const scalefac ) +{ + int i, sfb; + + for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++) + if (scalefac->l[sfb] == 0) + return 0; + + for (sfb = cod_info->sfb_smin; sfb < SBPSY_s; sfb++) + for (i = 0; i < 3; i++) + if (scalefac->s[sfb][i] == 0 && cod_info->subblock_gain[i] == 0) + return 0; + + return 1; +} + + + + +/************************************************************************* + * + * quant_compare() + * + * author/date?? + * + * several different codes to decide which quantization is better + * + *************************************************************************/ + +inline +static int +quant_compare( + const int experimentalX, + lame_internal_flags * const gfc, + const calc_noise_result * const best, + const calc_noise_result * const calc, + const int block_type ) +{ + /* + noise is given in decibels (dB) relative to masking thesholds. + + over_noise: ??? (the previous comment is fully wrong) + tot_noise: ??? (the previous comment is fully wrong) + max_noise: max quantization noise + + */ + int better; + + switch (experimentalX) { + default: + case 0: + better = calc->over_count < best->over_count + || ( calc->over_count == best->over_count && + calc->over_noise < best->over_noise ) + || ( calc->over_count == best->over_count && + calc->over_noise == best->over_noise && + calc->tot_noise < best->tot_noise ); + break; + case 1: + better = calc->max_noise < best->max_noise; + break; + case 2: + better = calc->tot_noise < best->tot_noise; + break; + case 3: + better = ( calc->tot_noise < (gfc->presetTune.use && + block_type != NORM_TYPE ? (best->tot_noise - gfc->presetTune.quantcomp_adjust_rh_tot) + : best->tot_noise ) && + calc->max_noise < (gfc->presetTune.use && + block_type != NORM_TYPE ? (best->max_noise - gfc->presetTune.quantcomp_adjust_rh_max) + : best->max_noise )); + break; + case 4: + better = ( calc->max_noise <= 0 && + best->max_noise > 2 ) + || ( calc->max_noise <= 0 && + best->max_noise < 0 && + best->max_noise > calc->max_noise-2 && + calc->tot_noise < best->tot_noise ) + || ( calc->max_noise <= 0 && + best->max_noise > 0 && + best->max_noise > calc->max_noise-2 && + calc->tot_noise < best->tot_noise+best->over_noise ) + || ( calc->max_noise > 0 && + best->max_noise > -0.5 && + best->max_noise > calc->max_noise-1 && + calc->tot_noise+calc->over_noise < best->tot_noise+best->over_noise ) + || ( calc->max_noise > 0 && + best->max_noise > -1 && + best->max_noise > calc->max_noise-1.5 && + calc->tot_noise+calc->over_noise+calc->over_noise < best->tot_noise+best->over_noise+best->over_noise ); + break; + case 5: + better = calc->over_noise < best->over_noise + || ( calc->over_noise == best->over_noise && + calc->tot_noise < best->tot_noise ); + break; + case 6: + better = calc->over_noise < best->over_noise + || ( calc->over_noise == best->over_noise && + ( calc->max_noise < best->max_noise + || ( calc->max_noise == best->max_noise && + calc->tot_noise <= best->tot_noise ) + )); + break; + case 7: + better = calc->over_count < best->over_count + || calc->over_noise < best->over_noise; + break; + case 8: + better = calc->klemm_noise < best->klemm_noise; + break; + } + + return better; +} + + + +/************************************************************************* + * + * amp_scalefac_bands() + * + * author/date?? + * + * Amplify the scalefactor bands that violate the masking threshold. + * See ISO 11172-3 Section C.1.5.4.3.5 + * + * distort[] = noise/masking + * distort[] > 1 ==> noise is not masked + * distort[] < 1 ==> noise is masked + * max_dist = maximum value of distort[] + * + * Three algorithms: + * noise_shaping_amp + * 0 Amplify all bands with distort[]>1. + * + * 1 Amplify all bands with distort[] >= max_dist^(.5); + * ( 50% in the db scale) + * + * 2 Amplify first band with distort[] >= max_dist; + * + * + * For algorithms 0 and 1, if max_dist < 1, then amplify all bands + * with distort[] >= .95*max_dist. This is to make sure we always + * amplify at least one band. + * + * + *************************************************************************/ +static void +amp_scalefac_bands( + lame_global_flags *gfp, + const gr_info *const cod_info, + III_scalefac_t *const scalefac, + III_psy_xmin *distort, + FLOAT8 xrpow[576] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int start, end, l,i,j,sfb; + FLOAT8 ifqstep34, trigger; + + if (cod_info->scalefac_scale == 0) { + ifqstep34 = 1.29683955465100964055; /* 2**(.75*.5)*/ + } else { + ifqstep34 = 1.68179283050742922612; /* 2**(.75*1) */ + } + + /* compute maximum value of distort[] */ + trigger = 0; + for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++) { + if (trigger < distort->l[sfb]) + trigger = distort->l[sfb]; + } + for (sfb = cod_info->sfb_smin; sfb < SBPSY_s; sfb++) { + for (i = 0; i < 3; i++ ) { + if (trigger < distort->s[sfb][i]) + trigger = distort->s[sfb][i]; + } + } + + switch (gfc->noise_shaping_amp) { + + case 3: + case 2: + /* amplify exactly 1 band */ + //trigger = distort_thresh; + break; + + case 1: + /* amplify bands within 50% of max (on db scale) */ + if (trigger>1.0) + trigger = pow(trigger, .5); + else + trigger *= .95; + break; + + case 0: + default: + /* ISO algorithm. amplify all bands with distort>1 */ + if (trigger>1.0) + trigger=1.0; + else + trigger *= .95; + break; + } + + for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++ ) { + start = gfc->scalefac_band.l[sfb]; + end = gfc->scalefac_band.l[sfb+1]; + if (distort->l[sfb]>=trigger ) { + if (gfc->noise_shaping_amp==3) { + if (gfc->pseudohalf.l[sfb]) { + gfc->pseudohalf.l[sfb] = 0; + goto done; + } + gfc->pseudohalf.l[sfb] = 1; + } + scalefac->l[sfb]++; + for ( l = start; l < end; l++ ) + xrpow[l] *= ifqstep34; + if (gfc->noise_shaping_amp==2 + ||gfc->noise_shaping_amp==3) goto done; + } + } + + for ( j=0,sfb = cod_info->sfb_smin; sfb < SBPSY_s; sfb++ ) { + start = gfc->scalefac_band.s[sfb]; + end = gfc->scalefac_band.s[sfb+1]; + for ( i = 0; i < 3; i++ ) { + int j2 = j; + if ( distort->s[sfb][i]>=trigger) { + if (gfc->noise_shaping_amp==3) { + if (gfc->pseudohalf.s[sfb][i]) { + gfc->pseudohalf.s[sfb][i] = 0; + goto done; + } + gfc->pseudohalf.s[sfb][i] = 1; + } + scalefac->s[sfb][i]++; + for (l = start; l < end; l++) + xrpow[j2++] *= ifqstep34; + if (gfc->noise_shaping_amp==2 + ||gfc->noise_shaping_amp==3) goto done; + } + j += end-start; + } + } + done: + return; +} + +/************************************************************************* + * + * inc_scalefac_scale() + * + * Takehiro Tominaga 2000-xx-xx + * + * turns on scalefac scale and adjusts scalefactors + * + *************************************************************************/ + +static void +inc_scalefac_scale ( + const lame_internal_flags * const gfc, + gr_info * const cod_info, + III_scalefac_t * const scalefac, + FLOAT8 xrpow[576] ) +{ + int start, end, l,i,j; + int sfb; + const FLOAT8 ifqstep34 = 1.29683955465100964055; + + for (sfb = 0; sfb < cod_info->sfb_lmax; sfb++) { + int s = scalefac->l[sfb] + (cod_info->preflag ? pretab[sfb] : 0); + if (s & 1) { + s++; + start = gfc->scalefac_band.l[sfb]; + end = gfc->scalefac_band.l[sfb+1]; + for (l = start; l < end; l++) + xrpow[l] *= ifqstep34; + } + scalefac->l[sfb] = s >> 1; + cod_info->preflag = 0; + } + + for (j = 0, sfb = cod_info->sfb_smin; sfb < SBPSY_s; sfb++) { + start = gfc->scalefac_band.s[sfb]; + end = gfc->scalefac_band.s[sfb+1]; + for (i = 0; i < 3; i++) { + int j2 = j; + if (scalefac->s[sfb][i] & 1) { + scalefac->s[sfb][i]++; + for (l = start; l < end; l++) + xrpow[j2++] *= ifqstep34; + } + scalefac->s[sfb][i] >>= 1; + j += end-start; + } + } + cod_info->scalefac_scale = 1; +} + + + +/************************************************************************* + * + * inc_subblock_gain() + * + * Takehiro Tominaga 2000-xx-xx + * + * increases the subblock gain and adjusts scalefactors + * + *************************************************************************/ + +static int +inc_subblock_gain ( + const lame_internal_flags * const gfc, + gr_info * const cod_info, + III_scalefac_t * const scalefac, + FLOAT8 xrpow[576] ) +{ + int window; + + for (window = 0; window < 3; window++) { + int s1, s2, l; + int sfb; + s1 = s2 = 0; + + for (sfb = cod_info->sfb_smin; sfb < 6; sfb++) { + if (s1 < scalefac->s[sfb][window]) + s1 = scalefac->s[sfb][window]; + } + for (; sfb < SBPSY_s; sfb++) { + if (s2 < scalefac->s[sfb][window]) + s2 = scalefac->s[sfb][window]; + } + + if (s1 < 16 && s2 < 8) + continue; + + if (cod_info->subblock_gain[window] >= 7) + return 1; + + /* even though there is no scalefactor for sfb12 + * subblock gain affects upper frequencies too, that's why + * we have to go up to SBMAX_s + */ + cod_info->subblock_gain[window]++; + for (sfb = cod_info->sfb_smin; sfb < SBMAX_s; sfb++) { + int i, width; + int s = scalefac->s[sfb][window]; + FLOAT8 amp; + + if (s < 0) + continue; + s = s - (4 >> cod_info->scalefac_scale); + if (s >= 0) { + scalefac->s[sfb][window] = s; + continue; + } + + scalefac->s[sfb][window] = 0; + width = gfc->scalefac_band.s[sfb] - gfc->scalefac_band.s[sfb+1]; + i = gfc->scalefac_band.s[sfb] * 3 + width * window; + amp = IPOW20(210 + (s << (cod_info->scalefac_scale + 1))); + for (l = 0; l < width; l++) { + xrpow[i++] *= amp; + } + } + } + return 0; +} + + + +/******************************************************************** + * + * balance_noise() + * + * Takehiro Tominaga /date?? + * Robert Hegemann 2000-09-06: made a function of it + * + * amplifies scalefactor bands, + * - if all are already amplified returns 0 + * - if some bands are amplified too much: + * * try to increase scalefac_scale + * * if already scalefac_scale was set + * try on short blocks to increase subblock gain + * + ********************************************************************/ +inline +static int +balance_noise ( + lame_global_flags *const gfp, + gr_info * const cod_info, + III_scalefac_t * const scalefac, + III_psy_xmin *distort, + FLOAT8 xrpow[576] ) +{ + lame_internal_flags *const gfc = (lame_internal_flags *)gfp->internal_flags; + int status; + + amp_scalefac_bands ( gfp, cod_info, scalefac, distort, xrpow); + + /* check to make sure we have not amplified too much + * loop_break returns 0 if there is an unamplified scalefac + * scale_bitcount returns 0 if no scalefactors are too large + */ + + status = loop_break (cod_info, scalefac); + + if (status) + return 0; /* all bands amplified */ + + /* not all scalefactors have been amplified. so these + * scalefacs are possibly valid. encode them: + */ + if (gfc->is_mpeg1) + status = scale_bitcount (scalefac, cod_info); + else + status = scale_bitcount_lsf (gfc, scalefac, cod_info); + + if (!status) + return 1; /* amplified some bands not exceeding limits */ + + /* some scalefactors are too large. + * lets try setting scalefac_scale=1 + */ + if ((gfc->noise_shaping > 1) && (!(gfc->presetTune.use && + gfc->ATH->adjust < gfc->presetTune.athadjust_switch_level))) { + memset(&gfc->pseudohalf, 0, sizeof(gfc->pseudohalf)); + if (!cod_info->scalefac_scale) { + inc_scalefac_scale (gfc, cod_info, scalefac, xrpow); + status = 0; + } else { + if (cod_info->block_type == SHORT_TYPE ) { + status = inc_subblock_gain (gfc, cod_info, scalefac, xrpow) + || loop_break (cod_info, scalefac); + } + } + } + + if (!status) { + if (gfc->is_mpeg1 == 1) + status = scale_bitcount (scalefac, cod_info); + else + status = scale_bitcount_lsf (gfc, scalefac, cod_info); + } + return !status; +} + + + +/************************************************************************ + * + * outer_loop () + * + * Function: The outer iteration loop controls the masking conditions + * of all scalefactorbands. It computes the best scalefac and + * global gain. This module calls the inner iteration loop + * + * mt 5/99 completely rewritten to allow for bit reservoir control, + * mid/side channels with L/R or mid/side masking thresholds, + * and chooses best quantization instead of last quantization when + * no distortion free quantization can be found. + * + * added VBR support mt 5/99 + * + * some code shuffle rh 9/00 + ************************************************************************/ + +static int +outer_loop ( + lame_global_flags *gfp, + gr_info * const cod_info, + const FLOAT8 xr[576], /* magnitudes of spectral values */ + const III_psy_xmin * const l3_xmin, /* allowed distortion of the scalefactor */ + III_scalefac_t * const scalefac, /* scalefactors */ + FLOAT8 xrpow[576], /* coloured magnitudes of spectral values */ + int l3enc[576], /* vector of quantized values ix(0..575) */ + const int ch, + const int targ_bits ) /* maximum allowed bits */ +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_scalefac_t save_scalefac; + gr_info save_cod_info; + FLOAT8 save_xrpow[576]; + III_psy_xmin distort; + calc_noise_result noise_info; + calc_noise_result best_noise_info; + int l3_enc_w[576]; + int iteration = 0; + int bits_found; + int huff_bits; + int real_bits; + int better; + int over; + + int copy = 0; + int age = 0; + + noise_info.over_count = 100; + noise_info.max_noise = 0; + noise_info.tot_noise = 0; + noise_info.over_noise = 0; + + best_noise_info.over_count = 100; + + bits_found = bin_search_StepSize (gfc, cod_info, targ_bits, + gfc->OldValue[ch], xrpow, l3_enc_w); + gfc->OldValue[ch] = cod_info->global_gain; + + /* BEGIN MAIN LOOP */ + do { + iteration ++; + + /* inner_loop starts with the initial quantization step computed above + * and slowly increases until the bits < huff_bits. + * Thus it is important not to start with too large of an inital + * quantization step. Too small is ok, but inner_loop will take longer + */ + huff_bits = targ_bits - cod_info->part2_length; + if (huff_bits < 0) { + assert(iteration != 1); + /* scale factors too large, not enough bits. + * use previous quantizaton */ + break; + } + /* if this is the first iteration, + * see if we can reuse the quantization computed in + * bin_search_StepSize above */ + + if (iteration == 1) { + if (bits_found > huff_bits) { + cod_info->global_gain++; + real_bits = inner_loop (gfc, cod_info, huff_bits, xrpow, + l3_enc_w); + } else { + real_bits = bits_found; + } + } else { + real_bits = inner_loop (gfc, cod_info, huff_bits, xrpow, + l3_enc_w); + } + + cod_info->part2_3_length = real_bits; + + /* compute the distortion in this quantization */ + if (gfc->noise_shaping) + /* coefficients and thresholds both l/r (or both mid/side) */ + over = calc_noise (gfc, xr, l3_enc_w, cod_info, l3_xmin, + scalefac, &distort, &noise_info); + else { + /* fast mode, no noise shaping, we are ready */ + best_noise_info = noise_info; + copy = 0; + memcpy(l3enc, l3_enc_w, sizeof(int)*576); + break; + } + + + /* check if this quantization is better + * than our saved quantization */ + if (iteration == 1) /* the first iteration is always better */ + better = 1; + else + better = quant_compare ((gfc->presetTune.use ? gfc->presetTune.quantcomp_current + : gfp->experimentalX), + gfc, &best_noise_info, &noise_info, cod_info->block_type); + + /* save data so we can restore this quantization later */ + if (better) { + copy = 0; + best_noise_info = noise_info; + memcpy(l3enc, l3_enc_w, sizeof(int)*576); + age = 0; + } + else + age ++; + + + /******************************************************************/ + /* stopping criterion */ + /******************************************************************/ + /* if no bands with distortion and -X0, we are done */ + if (0==gfc->noise_shaping_stop && + 0==gfp->experimentalX && + (over == 0 || best_noise_info.over_count == 0) ) + break; + /* Otherwise, allow up to 3 unsuccesful tries in serial, then stop + * if our best quantization so far had no distorted bands. This + * gives us more possibilities for different quant_compare modes. + * Much more than 3 makes not a big difference, it is only slower. + */ + if (age > 3 && best_noise_info.over_count == 0) + break; + + /* Check if the last scalefactor band is distorted. + * in VBR mode we can't get rid of the distortion, so quit now + * and VBR mode will try again with more bits. + * (makes a 10% speed increase, the files I tested were + * binary identical, 2000/05/20 Robert.Hegemann@gmx.de) + * distort[] > 1 means noise > allowed noise + */ + if (gfc->sfb21_extra) { + if (cod_info->block_type == SHORT_TYPE) { + if (distort.s[SBMAX_s-1][0] > 1 || + distort.s[SBMAX_s-1][1] > 1 || + distort.s[SBMAX_s-1][2] > 1) break; + } else { + if (distort.l[SBMAX_l-1] > 1) break; + } + } + + /* save data so we can restore this quantization later */ + if (better) { + copy = 1; + save_scalefac = *scalefac; + save_cod_info = *cod_info; + if (gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh) { + /* store for later reuse */ + memcpy(save_xrpow, xrpow, sizeof(FLOAT8)*576); + } + } + + if (balance_noise (gfp, cod_info, scalefac, &distort, xrpow) == 0) + break; + } + while (1); /* main iteration loop, breaks adjusted */ + + /* finish up + */ + if (copy) { + *cod_info = save_cod_info; + *scalefac = save_scalefac; + if (gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh) + /* restore for reuse on next try */ + memcpy(xrpow, save_xrpow, sizeof(FLOAT8)*576); + } + cod_info->part2_3_length += cod_info->part2_length; + + assert (cod_info->global_gain < 256); + + return best_noise_info.over_count; +} + + + + +/************************************************************************ + * + * iteration_finish() + * + * Robert Hegemann 2000-09-06 + * + * update reservoir status after FINAL quantization/bitrate + * + * rh 2000-09-06: it will not work with CBR due to the bitstream formatter + * you will get "Error: MAX_HEADER_BUF too small in bitstream.c" + * + ************************************************************************/ + +static void +iteration_finish ( + lame_internal_flags *gfc, + FLOAT8 xr [2][2][576], + int l3_enc [2][2][576], + III_scalefac_t scalefac[2][2], + const int mean_bits ) +{ + III_side_info_t *l3_side = &gfc->l3_side; + int gr, ch, i; + + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + gr_info *cod_info = &l3_side->gr[gr].ch[ch].tt; + + /* try some better scalefac storage + */ + best_scalefac_store (gfc, gr, ch, l3_enc, l3_side, scalefac); + + /* best huffman_divide may save some bits too + */ + if (gfc->use_best_huffman == 1) + best_huffman_divide (gfc, cod_info, l3_enc[gr][ch]); + + /* update reservoir status after FINAL quantization/bitrate + */ + ResvAdjust (gfc, cod_info, l3_side, mean_bits); + + /* set the sign of l3_enc from the sign of xr + */ + for (i = 0; i < 576; i++) { + if (xr[gr][ch][i] < 0) l3_enc[gr][ch][i] *= -1; + } + } /* for ch */ + } /* for gr */ + + ResvFrameEnd (gfc, l3_side, mean_bits); +} + + + +/********************************************************************* + * + * VBR_encode_granule() + * + * 2000-09-04 Robert Hegemann + * + *********************************************************************/ + +static void +VBR_encode_granule ( + lame_global_flags *gfp, + gr_info * const cod_info, + FLOAT8 xr[576], /* magnitudes of spectral values */ + const III_psy_xmin * const l3_xmin, /* allowed distortion of the scalefactor */ + III_scalefac_t * const scalefac, /* scalefactors */ + FLOAT8 xrpow[576], /* coloured magnitudes of spectral values */ + int l3_enc[576], /* vector of quantized values ix(0..575) */ + const int ch, + int min_bits, + int max_bits ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + gr_info bst_cod_info; + III_scalefac_t bst_scalefac; + FLOAT8 bst_xrpow [576]; + int bst_l3_enc[576]; + int Max_bits = max_bits; + int real_bits = max_bits+1; + int this_bits = (max_bits+min_bits)/2; + int dbits, over, found = 0; + int sfb21_extra = gfc->sfb21_extra; + + assert(Max_bits <= MAX_BITS); + + /* search within round about 40 bits of optimal + */ + do { + assert(this_bits >= min_bits); + assert(this_bits <= max_bits); + assert(min_bits <= max_bits); + + if (this_bits > Max_bits-42) + gfc->sfb21_extra = 0; + else + gfc->sfb21_extra = sfb21_extra; + + over = outer_loop ( gfp, cod_info, xr, l3_xmin, scalefac, + xrpow, l3_enc, ch, this_bits ); + + /* is quantization as good as we are looking for ? + * in this case: is no scalefactor band distorted? + */ + if (over <= 0) { + found = 1; + /* now we know it can be done with "real_bits" + * and maybe we can skip some iterations + */ + real_bits = cod_info->part2_3_length; + + /* store best quantization so far + */ + bst_cod_info = *cod_info; + bst_scalefac = *scalefac; + memcpy(bst_xrpow, xrpow, sizeof(FLOAT8)*576); + memcpy(bst_l3_enc, l3_enc, sizeof(int)*576); + + /* try with fewer bits + */ + max_bits = real_bits-32; + dbits = max_bits-min_bits; + this_bits = (max_bits+min_bits)/2; + } + else { + /* try with more bits + */ + min_bits = this_bits+32; + dbits = max_bits-min_bits; + this_bits = (max_bits+min_bits)/2; + + if (found) { + found = 2; + /* start again with best quantization so far + */ + *cod_info = bst_cod_info; + *scalefac = bst_scalefac; + memcpy(xrpow, bst_xrpow, sizeof(FLOAT8)*576); + } + } + } while (dbits>12); + + gfc->sfb21_extra = sfb21_extra; + + /* found=0 => nothing found, use last one + * found=1 => we just found the best and left the loop + * found=2 => we restored a good one and have now l3_enc to restore too + */ + if (found==2) { + memcpy(l3_enc, bst_l3_enc, sizeof(int)*576); + } + assert(cod_info->part2_3_length <= Max_bits); + +} + + + +/************************************************************************ + * + * get_framebits() + * + * Robert Hegemann 2000-09-05 + * + * calculates + * * how many bits are available for analog silent granules + * * how many bits to use for the lowest allowed bitrate + * * how many bits each bitrate would provide + * + ************************************************************************/ + +static void +get_framebits ( + lame_global_flags *gfp, + int * const analog_mean_bits, + int * const min_mean_bits, + int frameBits[15] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int bitsPerFrame, mean_bits, i; + III_side_info_t *l3_side = &gfc->l3_side; + + /* always use at least this many bits per granule per channel + * unless we detect analog silence, see below + */ + gfc->bitrate_index = gfc->VBR_min_bitrate; + getframebits (gfp, &bitsPerFrame, &mean_bits); + *min_mean_bits = mean_bits / gfc->channels_out; + + /* bits for analog silence + */ + gfc->bitrate_index = 1; + getframebits (gfp, &bitsPerFrame, &mean_bits); + *analog_mean_bits = mean_bits / gfc->channels_out; + + for (i = 1; i <= gfc->VBR_max_bitrate; i++) { + gfc->bitrate_index = i; + getframebits (gfp, &bitsPerFrame, &mean_bits); + frameBits[i] = ResvFrameBegin (gfp, l3_side, mean_bits, bitsPerFrame); + } +} + + + +/************************************************************************ + * + * calc_min_bits() + * + * Robert Hegemann 2000-09-04 + * + * determine minimal bit skeleton + * + ************************************************************************/ +inline +static int +calc_min_bits ( + lame_global_flags *gfp, + const gr_info * const cod_info, + const int pe, + const FLOAT8 ms_ener_ratio, + const int bands, + const int mch_bits, + const int analog_mean_bits, + const int min_mean_bits, + const int analog_silence, + const int ch ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int min_bits, min_pe_bits; + + if (gfc->nsPsy.use) return 126; + /* changed minimum from 1 to 126 bits + * the iteration loops require a minimum of bits + * for each granule to start with; robert 2001-07-02 */ + + /* base amount of minimum bits + */ + min_bits = Max (126, min_mean_bits); + + if (gfc->mode_ext == MPG_MD_MS_LR && ch == 1) + min_bits = Max (min_bits, mch_bits/5); + + /* bit skeleton based on PE + */ + if (cod_info->block_type == SHORT_TYPE) + /* if LAME switches to short blocks then pe is + * >= 1000 on medium surge + * >= 3000 on big surge + */ + min_pe_bits = (pe-350) * bands/39; + else + min_pe_bits = (pe-350) * bands/22; + + if (gfc->mode_ext == MPG_MD_MS_LR && ch == 1) { + /* side channel will use a lower bit skeleton based on PE + */ + FLOAT8 fac = .33 * (.5 - ms_ener_ratio) / .5; + min_pe_bits = (int)(min_pe_bits * ((1-fac)/(1+fac))); + } + min_pe_bits = Min (min_pe_bits, (1820 * gfp->out_samplerate / 44100)); + + /* determine final minimum bits + */ + if (analog_silence && !gfp->VBR_hard_min) + min_bits = analog_mean_bits; + else + min_bits = Max (min_bits, min_pe_bits); + + return min_bits; +} + + + +/********************************************************************* + * + * VBR_prepare() + * + * 2000-09-04 Robert Hegemann + * + * * converts LR to MS coding when necessary + * * calculates allowed/adjusted quantization noise amounts + * * detects analog silent frames + * + * some remarks: + * - lower masking depending on Quality setting + * - quality control together with adjusted ATH MDCT scaling + * on lower quality setting allocate more noise from + * ATH masking, and on higher quality setting allocate + * less noise from ATH masking. + * - experiments show that going more than 2dB over GPSYCHO's + * limits ends up in very annoying artefacts + * + *********************************************************************/ + +/* RH: this one needs to be overhauled sometime */ + +static int +VBR_prepare ( + lame_global_flags *gfp, + FLOAT8 pe [2][2], + FLOAT8 ms_ener_ratio [2], + FLOAT8 xr [2][2][576], + III_psy_ratio ratio [2][2], + III_psy_xmin l3_xmin [2][2], + int frameBits [16], + int *analog_mean_bits, + int *min_mean_bits, + int min_bits [2][2], + int max_bits [2][2], + int bands [2][2] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + + + FLOAT8 masking_lower_db, adjust = 0.0; + int gr, ch; + int analog_silence = 1; + int bpf, avg, mxb, bits = 0; + + gfc->bitrate_index = gfc->VBR_max_bitrate; + getframebits (gfp, &bpf, &avg); + bpf = ResvFrameBegin (gfp, &gfc->l3_side, avg, bpf ); + avg = (bpf - 8*gfc->sideinfo_len) / gfc->mode_gr; + + get_framebits (gfp, analog_mean_bits, min_mean_bits, frameBits); + + for (gr = 0; gr < gfc->mode_gr; gr++) { + mxb = on_pe (gfp, pe, &gfc->l3_side, max_bits[gr], avg, gr); + if (gfc->mode_ext == MPG_MD_MS_LR) { + ms_convert (xr[gr], xr[gr]); + reduce_side (max_bits[gr], ms_ener_ratio[gr], avg, mxb); + } + for (ch = 0; ch < gfc->channels_out; ++ch) { + gr_info *cod_info = &gfc->l3_side.gr[gr].ch[ch].tt; + + if (gfc->nsPsy.use && gfp->VBR == vbr_rh) { + if (cod_info->block_type == NORM_TYPE) + adjust = 1.28/(1+exp(3.5-pe[gr][ch]/300.))-0.05; + else + adjust = 2.56/(1+exp(3.5-pe[gr][ch]/300.))-0.14; + } + masking_lower_db = gfc->VBR->mask_adjust - adjust; + gfc->masking_lower = pow (10.0, masking_lower_db * 0.1); + + bands[gr][ch] = calc_xmin (gfp, xr[gr][ch], ratio[gr]+ch, + cod_info, l3_xmin[gr]+ch); + if (bands[gr][ch]) + analog_silence = 0; + + min_bits[gr][ch] = calc_min_bits (gfp, cod_info, (int)pe[gr][ch], + ms_ener_ratio[gr], bands[gr][ch], + 0, *analog_mean_bits, + *min_mean_bits, analog_silence, ch); + + bits += max_bits[gr][ch]; + } + } + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + if (bits > frameBits[gfc->VBR_max_bitrate]) { + max_bits[gr][ch] *= frameBits[gfc->VBR_max_bitrate]; + max_bits[gr][ch] /= bits; + } + if (min_bits[gr][ch] > max_bits[gr][ch]) + min_bits[gr][ch] = max_bits[gr][ch]; + + } /* for ch */ + } /* for gr */ + + *min_mean_bits = Max(*min_mean_bits, 126); + + return analog_silence; +} + + +inline +void bitpressure_strategy1( + lame_internal_flags * gfc, + III_psy_xmin l3_xmin[2][2], + int min_bits[2][2], + int max_bits[2][2] ) +{ + int gr, ch, sfb; + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + if (gfc->l3_side.gr[gr].ch[ch].tt.block_type == SHORT_TYPE) { + for (sfb = 0; sfb < SBMAX_s; sfb++) { + l3_xmin[gr][ch].s[sfb][0] *= 1.+.029*sfb*sfb/SBMAX_s/SBMAX_s; + l3_xmin[gr][ch].s[sfb][1] *= 1.+.029*sfb*sfb/SBMAX_s/SBMAX_s; + l3_xmin[gr][ch].s[sfb][2] *= 1.+.029*sfb*sfb/SBMAX_s/SBMAX_s; + } + } + else { + for (sfb = 0; sfb < SBMAX_l; sfb++) + l3_xmin[gr][ch].l[sfb] *= 1.+.029*sfb*sfb/SBMAX_l/SBMAX_l; + } + max_bits[gr][ch] = Max(min_bits[gr][ch], 0.9*max_bits[gr][ch]); + } + } +} + +inline +void bitpressure_strategy2( + lame_internal_flags * gfc, + int bpf, int used, int save_bits[2][2], + int min_bits[2][2], int max_bits[2][2] ) +{ + int gr, ch; + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + max_bits[gr][ch] = save_bits[gr][ch]; + max_bits[gr][ch] *= bpf; + max_bits[gr][ch] /= used; + max_bits[gr][ch] = Max(min_bits[gr][ch],max_bits[gr][ch]); + } + } +} + +/************************************************************************ + * + * VBR_iteration_loop() + * + * tries to find out how many bits are needed for each granule and channel + * to get an acceptable quantization. An appropriate bitrate will then be + * choosed for quantization. rh 8/99 + * + * Robert Hegemann 2000-09-06 rewrite + * + ************************************************************************/ + +void +VBR_iteration_loop ( + lame_global_flags *gfp, + FLOAT8 pe [2][2], + FLOAT8 ms_ener_ratio[2], + FLOAT8 xr [2][2][576], + III_psy_ratio ratio [2][2], + int l3_enc [2][2][576], + III_scalefac_t scalefac [2][2] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_psy_xmin l3_xmin[2][2]; + + FLOAT8 xrpow[576]; + int bands[2][2]; + int frameBits[15]; + int bitsPerFrame; + int save_bits[2][2]; + int used_bits, used_bits2; + int bits; + int min_bits[2][2], max_bits[2][2]; + int analog_mean_bits, min_mean_bits; + int mean_bits; + int ch, gr, analog_silence; + gr_info *cod_info; + III_side_info_t *l3_side = &gfc->l3_side; + + analog_silence = VBR_prepare (gfp, pe, ms_ener_ratio, xr, ratio, + l3_xmin, frameBits, &analog_mean_bits, + &min_mean_bits, min_bits, max_bits, bands); + + /*---------------------------------*/ + for(;;) { + + /* quantize granules with lowest possible number of bits + */ + + used_bits = 0; + used_bits2 = 0; + + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + int ret; + cod_info = &l3_side->gr[gr].ch[ch].tt; + + /* init_outer_loop sets up cod_info, scalefac and xrpow + */ + ret = init_outer_loop(gfc, cod_info, &scalefac[gr][ch], + xr[gr][ch], xrpow); + if (ret == 0 || max_bits[gr][ch] == 0) { + /* xr contains no energy + * l3_enc, our encoding data, will be quantized to zero + */ + memset(l3_enc[gr][ch], 0, sizeof(int)*576); + save_bits[gr][ch] = 0; + continue; /* with next channel */ + } + + if (gfp->VBR == vbr_mtrh) { + ret = VBR_noise_shaping2 (gfp, xr[gr][ch], xrpow, l3_enc[gr][ch], + min_bits[gr][ch], max_bits[gr][ch], + &scalefac[gr][ch], + &l3_xmin[gr][ch], gr, ch ); + if (ret < 0) + cod_info->part2_3_length = 100000; + } + else + VBR_encode_granule (gfp, cod_info, xr[gr][ch], &l3_xmin[gr][ch], + &scalefac[gr][ch], xrpow, l3_enc[gr][ch], + ch, min_bits[gr][ch], max_bits[gr][ch] ); + + used_bits += cod_info->part2_3_length; + save_bits[gr][ch] = Min(MAX_BITS, cod_info->part2_3_length); + used_bits2 += Min(MAX_BITS, cod_info->part2_3_length); + } /* for ch */ + } /* for gr */ + + /* find lowest bitrate able to hold used bits + */ + if (analog_silence && !gfp->VBR_hard_min) + /* we detected analog silence and the user did not specify + * any hard framesize limit, so start with smallest possible frame + */ + gfc->bitrate_index = 1; + else + gfc->bitrate_index = gfc->VBR_min_bitrate; + + for( ; gfc->bitrate_index < gfc->VBR_max_bitrate; gfc->bitrate_index++) { + if (used_bits <= frameBits[gfc->bitrate_index]) break; + } + + getframebits (gfp, &bitsPerFrame, &mean_bits); + bits = ResvFrameBegin (gfp, l3_side, mean_bits, bitsPerFrame); + + if (used_bits <= bits) break; + + switch ( gfc -> VBR -> bitpressure ) { + default: + case 1: bitpressure_strategy1( gfc, l3_xmin, min_bits, max_bits ); + break; + case 2: bitpressure_strategy2( gfc, frameBits[gfc->bitrate_index], + used_bits2, save_bits, min_bits, max_bits ); + break; + } + + } /* breaks adjusted */ + /*--------------------------------------*/ + + iteration_finish (gfc, xr, l3_enc, scalefac, mean_bits); +} + + + + + + +/******************************************************************** + * + * calc_target_bits() + * + * calculates target bits for ABR encoding + * + * mt 2000/05/31 + * + ********************************************************************/ + +static void +calc_target_bits ( + lame_global_flags * gfp, + FLOAT8 pe [2][2], + FLOAT8 ms_ener_ratio [2], + int targ_bits [2][2], + int *analog_silence_bits, + int *max_frame_bits ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_side_info_t *l3_side = &gfc->l3_side; + FLOAT8 res_factor; + int gr, ch, totbits, mean_bits, bitsPerFrame; + + gfc->bitrate_index = gfc->VBR_max_bitrate; + getframebits (gfp, &bitsPerFrame, &mean_bits); + *max_frame_bits = ResvFrameBegin (gfp, l3_side, mean_bits, bitsPerFrame); + + gfc->bitrate_index = 1; + getframebits (gfp, &bitsPerFrame, &mean_bits); + *analog_silence_bits = mean_bits / gfc->channels_out; + + mean_bits = gfp->VBR_mean_bitrate_kbps * gfp->framesize * 1000; + mean_bits /= gfp->out_samplerate; + mean_bits -= gfc->sideinfo_len*8; + mean_bits /= gfc->mode_gr; + + /* + res_factor is the percentage of the target bitrate that should + be used on average. the remaining bits are added to the + bitreservoir and used for difficult to encode frames. + + Since we are tracking the average bitrate, we should adjust + res_factor "on the fly", increasing it if the average bitrate + is greater than the requested bitrate, and decreasing it + otherwise. Reasonable ranges are from .9 to 1.0 + + Until we get the above suggestion working, we use the following + tuning: + compression ratio res_factor + 5.5 (256kbps) 1.0 no need for bitreservoir + 11 (128kbps) .93 7% held for reservoir + + with linear interpolation for other values. + + */ + res_factor = .93 + .07 * (11.0 - gfp->compression_ratio) / (11.0 - 5.5); + if (res_factor < .90) + res_factor = .90; + if (res_factor > 1.00) + res_factor = 1.00; + + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + targ_bits[gr][ch] = res_factor * (mean_bits / gfc->channels_out); + + if (pe[gr][ch] > 700) { + int add_bits = (pe[gr][ch] - 700) / 1.4; + + gr_info *cod_info = &l3_side->gr[gr].ch[ch].tt; + targ_bits[gr][ch] = res_factor * (mean_bits / gfc->channels_out); + + /* short blocks use a little extra, no matter what the pe */ + if (cod_info->block_type == SHORT_TYPE) { + if (add_bits < mean_bits/4) + add_bits = mean_bits/4; + } + /* at most increase bits by 1.5*average */ + if (add_bits > mean_bits*3/4) + add_bits = mean_bits*3/4; + else + if (add_bits < 0) + add_bits = 0; + + targ_bits[gr][ch] += add_bits; + } + }/* for ch */ + } /* for gr */ + + if (gfc->mode_ext == MPG_MD_MS_LR) + for (gr = 0; gr < gfc->mode_gr; gr++) { + reduce_side (targ_bits[gr], ms_ener_ratio[gr], mean_bits, + MAX_BITS); + } + + /* sum target bits + */ + totbits=0; + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + if (targ_bits[gr][ch] > MAX_BITS) + targ_bits[gr][ch] = MAX_BITS; + totbits += targ_bits[gr][ch]; + } + } + + /* repartion target bits if needed + */ + if (totbits > *max_frame_bits) { + for(gr = 0; gr < gfc->mode_gr; gr++) { + for(ch = 0; ch < gfc->channels_out; ch++) { + targ_bits[gr][ch] *= *max_frame_bits; + targ_bits[gr][ch] /= totbits; + } + } + } +} + + + + + + +/******************************************************************** + * + * ABR_iteration_loop() + * + * encode a frame with a disired average bitrate + * + * mt 2000/05/31 + * + ********************************************************************/ + +void +ABR_iteration_loop( + lame_global_flags *gfp, + FLOAT8 pe [2][2], + FLOAT8 ms_ener_ratio[2], + FLOAT8 xr [2][2][576], + III_psy_ratio ratio [2][2], + int l3_enc [2][2][576], + III_scalefac_t scalefac [2][2] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_psy_xmin l3_xmin; + FLOAT8 xrpow[576]; + int targ_bits[2][2]; + int bitsPerFrame, mean_bits, totbits, max_frame_bits; + int ch, gr, ath_over, ret; + int analog_silence_bits; + gr_info *cod_info; + III_side_info_t *l3_side = &gfc->l3_side; + + calc_target_bits (gfp, pe, ms_ener_ratio, targ_bits, + &analog_silence_bits, &max_frame_bits); + + /* encode granules + */ + totbits=0; + for (gr = 0; gr < gfc->mode_gr; gr++) { + + if (gfc->mode_ext == MPG_MD_MS_LR) + ms_convert (xr[gr], xr[gr]); + + for (ch = 0; ch < gfc->channels_out; ch++) { + cod_info = &l3_side->gr[gr].ch[ch].tt; + + /* cod_info, scalefac and xrpow get initialized in init_outer_loop + */ + ret = init_outer_loop(gfc, cod_info, &scalefac[gr][ch], + xr[gr][ch], xrpow); + if (ret == 0) { + /* xr contains no energy + * l3_enc, our encoding data, will be quantized to zero + */ + memset(l3_enc[gr][ch], 0, sizeof(int)*576); + } + else { + /* xr contains energy we will have to encode + * calculate the masking abilities + * find some good quantization in outer_loop + */ + ath_over = calc_xmin (gfp, xr[gr][ch], &ratio[gr][ch], + cod_info, &l3_xmin); + if (0 == ath_over) /* analog silence */ + targ_bits[gr][ch] = analog_silence_bits; + + outer_loop (gfp, cod_info, xr[gr][ch], &l3_xmin, + &scalefac[gr][ch], xrpow, l3_enc[gr][ch], + ch, targ_bits[gr][ch]); + } + + totbits += cod_info->part2_3_length; + } /* ch */ + } /* gr */ + + /* find a bitrate which can handle totbits + */ + for (gfc->bitrate_index = gfc->VBR_min_bitrate ; + gfc->bitrate_index <= gfc->VBR_max_bitrate; + gfc->bitrate_index++ ) { + getframebits (gfp, &bitsPerFrame, &mean_bits); + max_frame_bits = ResvFrameBegin (gfp, l3_side, mean_bits, bitsPerFrame); + if (totbits <= max_frame_bits) break; + } + assert (gfc->bitrate_index <= gfc->VBR_max_bitrate); + + iteration_finish (gfc, xr, l3_enc, scalefac, mean_bits); +} + + + + + + +/************************************************************************ + * + * iteration_loop() + * + * author/date?? + * + * encodes one frame of MP3 data with constant bitrate + * + ************************************************************************/ + +void +iteration_loop( + lame_global_flags *gfp, + FLOAT8 pe [2][2], + FLOAT8 ms_ener_ratio[2], + FLOAT8 xr [2][2][576], + III_psy_ratio ratio [2][2], + int l3_enc [2][2][576], + III_scalefac_t scalefac [2][2] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_psy_xmin l3_xmin[2]; + FLOAT8 xrpow[576]; + int targ_bits[2]; + int bitsPerFrame; + int mean_bits, max_bits; + int gr, ch, i; + III_side_info_t *l3_side = &gfc->l3_side; + gr_info *cod_info; + + getframebits (gfp, &bitsPerFrame, &mean_bits); + ResvFrameBegin (gfp, l3_side, mean_bits, bitsPerFrame ); + + /* quantize! */ + for (gr = 0; gr < gfc->mode_gr; gr++) { + + /* calculate needed bits + */ + max_bits = on_pe (gfp, pe, l3_side, targ_bits, mean_bits, gr); + + if (gfc->mode_ext == MPG_MD_MS_LR) { + ms_convert (xr[gr], xr[gr]); + reduce_side (targ_bits, ms_ener_ratio[gr], mean_bits, max_bits); + } + + for (ch=0 ; ch < gfc->channels_out ; ch ++) { + cod_info = &l3_side->gr[gr].ch[ch].tt; + + /* init_outer_loop sets up cod_info, scalefac and xrpow + */ + i = init_outer_loop(gfc, cod_info, &scalefac[gr][ch], + xr[gr][ch], xrpow); + if (i == 0) { + /* xr contains no energy, l3_enc will be quantized to zero + */ + memset(l3_enc[gr][ch], 0, sizeof(int)*576); + } + else { + /* xr contains energy we will have to encode + * calculate the masking abilities + * find some good quantization in outer_loop + */ + calc_xmin (gfp, xr[gr][ch], &ratio[gr][ch], cod_info, + &l3_xmin[ch]); + outer_loop (gfp, cod_info, xr[gr][ch], &l3_xmin[ch], + &scalefac[gr][ch], xrpow, l3_enc[gr][ch], + ch, targ_bits[ch]); + } + assert (cod_info->part2_3_length <= MAX_BITS); + + /* try some better scalefac storage + */ + best_scalefac_store (gfc, gr, ch, l3_enc, l3_side, scalefac); + + /* best huffman_divide may save some bits too + */ + if (gfc->use_best_huffman == 1) + best_huffman_divide (gfc, cod_info, l3_enc[gr][ch]); + + /* update reservoir status after FINAL quantization/bitrate + */ +#undef NORES_TEST +#ifndef NORES_TEST + ResvAdjust (gfc, cod_info, l3_side, mean_bits); +#endif + /* set the sign of l3_enc from the sign of xr + */ + for (i = 0; i < 576; i++) { + if (xr[gr][ch][i] < 0) l3_enc[gr][ch][i] *= -1; + } + } /* for ch */ + } /* for gr */ + +#ifdef NORES_TEST + /* replace ResvAdjust above with this code if you do not want + the second granule to use bits saved by the first granule. + Requires using the --nores. This is useful for testing only */ + for (gr = 0; gr < gfc->mode_gr; gr++) { + for (ch = 0; ch < gfc->channels_out; ch++) { + cod_info = &l3_side->gr[gr].ch[ch].tt; + ResvAdjust (gfc, cod_info, l3_side, mean_bits); + } + } +#endif + + ResvFrameEnd (gfc, l3_side, mean_bits); +} + + + diff --git a/lib/lame/quantize.h b/lib/lame/quantize.h new file mode 100644 index 0000000..832f92f --- /dev/null +++ b/lib/lame/quantize.h @@ -0,0 +1,45 @@ +/* + * MP3 quantization + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_QUANTIZE_H +#define LAME_QUANTIZE_H + +#include "util.h" + +void iteration_loop( lame_global_flags *gfp, + FLOAT8 pe[2][2], FLOAT8 ms_ratio[2], + FLOAT8 xr_org[2][2][576], III_psy_ratio ratio[2][2], + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2]); + +void VBR_iteration_loop( lame_global_flags *gfp, + FLOAT8 pe[2][2], FLOAT8 ms_ratio[2], + FLOAT8 xr_org[2][2][576], III_psy_ratio ratio[2][2], + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2]); + +void ABR_iteration_loop( lame_global_flags *gfp, + FLOAT8 pe[2][2], FLOAT8 ms_ratio[2], + FLOAT8 xr_org[2][2][576], III_psy_ratio ratio[2][2], + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2]); + +#endif /* LAME_QUANTIZE_H */ diff --git a/lib/lame/quantize_pvt.c b/lib/lame/quantize_pvt.c new file mode 100644 index 0000000..df775f7 --- /dev/null +++ b/lib/lame/quantize_pvt.c @@ -0,0 +1,1206 @@ +/* + * quantize_pvt source file + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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: quantize_pvt.c,v 1.1 2002/04/28 17:30:26 kramm Exp $ */ +#include "config_static.h" + +#include +#include "util.h" +#include "lame-analysis.h" +#include "tables.h" +#include "reservoir.h" +#include "quantize_pvt.h" + +#ifdef WITH_DMALLOC +#include +#endif + + +#define NSATHSCALE 100 // Assuming dynamic range=96dB, this value should be 92 + +const char slen1_tab [16] = { 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 }; +const char slen2_tab [16] = { 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 }; + + +/* + The following table is used to implement the scalefactor + partitioning for MPEG2 as described in section + 2.4.3.2 of the IS. The indexing corresponds to the + way the tables are presented in the IS: + + [table_number][row_in_table][column of nr_of_sfb] +*/ +const int nr_of_sfb_block [6] [3] [4] = +{ + { + {6, 5, 5, 5}, + {9, 9, 9, 9}, + {6, 9, 9, 9} + }, + { + {6, 5, 7, 3}, + {9, 9, 12, 6}, + {6, 9, 12, 6} + }, + { + {11, 10, 0, 0}, + {18, 18, 0, 0}, + {15,18,0,0} + }, + { + {7, 7, 7, 0}, + {12, 12, 12, 0}, + {6, 15, 12, 0} + }, + { + {6, 6, 6, 3}, + {12, 9, 9, 6}, + {6, 12, 9, 6} + }, + { + {8, 8, 5, 0}, + {15,12,9,0}, + {6,18,9,0} + } +}; + + +/* Table B.6: layer3 preemphasis */ +const char pretab [SBMAX_l] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 2, 2, 3, 3, 3, 2, 0 +}; + +/* + Here are MPEG1 Table B.8 and MPEG2 Table B.1 + -- Layer III scalefactor bands. + Index into this using a method such as: + idx = fr_ps->header->sampling_frequency + + (fr_ps->header->version * 3) +*/ + + +const scalefac_struct sfBandIndex[9] = +{ + { /* Table B.2.b: 22.05 kHz */ + {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {0,4,8,12,18,24,32,42,56,74,100,132,174,192} + }, + { /* Table B.2.c: 24 kHz */ /* docs: 332. mpg123(broken): 330 */ + {0,6,12,18,24,30,36,44,54,66,80,96,114,136,162,194,232,278, 332, 394,464,540,576}, + {0,4,8,12,18,26,36,48,62,80,104,136,180,192} + }, + { /* Table B.2.a: 16 kHz */ + {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {0,4,8,12,18,26,36,48,62,80,104,134,174,192} + }, + { /* Table B.8.b: 44.1 kHz */ + {0,4,8,12,16,20,24,30,36,44,52,62,74,90,110,134,162,196,238,288,342,418,576}, + {0,4,8,12,16,22,30,40,52,66,84,106,136,192} + }, + { /* Table B.8.c: 48 kHz */ + {0,4,8,12,16,20,24,30,36,42,50,60,72,88,106,128,156,190,230,276,330,384,576}, + {0,4,8,12,16,22,28,38,50,64,80,100,126,192} + }, + { /* Table B.8.a: 32 kHz */ + {0,4,8,12,16,20,24,30,36,44,54,66,82,102,126,156,194,240,296,364,448,550,576}, + {0,4,8,12,16,22,30,42,58,78,104,138,180,192} + }, + { /* MPEG-2.5 11.025 kHz */ + {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {0/3,12/3,24/3,36/3,54/3,78/3,108/3,144/3,186/3,240/3,312/3,402/3,522/3,576/3} + }, + { /* MPEG-2.5 12 kHz */ + {0,6,12,18,24,30,36,44,54,66,80,96,116,140,168,200,238,284,336,396,464,522,576}, + {0/3,12/3,24/3,36/3,54/3,78/3,108/3,144/3,186/3,240/3,312/3,402/3,522/3,576/3} + }, + { /* MPEG-2.5 8 kHz */ + {0,12,24,36,48,60,72,88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576}, + {0/3,24/3,48/3,72/3,108/3,156/3,216/3,288/3,372/3,480/3,486/3,492/3,498/3,576/3} + } +}; + + + +FLOAT8 pow20[Q_MAX]; +FLOAT8 ipow20[Q_MAX]; +FLOAT8 iipow20[Q_MAX]; +FLOAT8 *iipow20_; +FLOAT8 pow43[PRECALC_SIZE]; +/* initialized in first call to iteration_init */ +FLOAT8 adj43asm[PRECALC_SIZE]; +FLOAT8 adj43[PRECALC_SIZE]; + +/************************************************************************/ +/* initialization for iteration_loop */ +/************************************************************************/ +void +iteration_init( lame_global_flags *gfp) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_side_info_t * const l3_side = &gfc->l3_side; + int i; + + if ( gfc->iteration_init_init==0 ) { + gfc->iteration_init_init=1; + + l3_side->main_data_begin = 0; + compute_ath(gfp,gfc->ATH->l,gfc->ATH->s); + + pow43[0] = 0.0; + for(i=1;iinternal_flags; + FLOAT8 ath; + + ath = ATHformula( f , gfp ); + + if (gfc->nsPsy.use) { + ath -= NSATHSCALE; + } else { + ath -= 114; + } + + /* modify the MDCT scaling for the ATH */ + ath -= gfp->ATHlower; + + /* convert to energy */ + ath = pow( 10.0, ath/10.0 ); + return ath; +} + + +void compute_ath( lame_global_flags *gfp, FLOAT8 ATH_l[], FLOAT8 ATH_s[] ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int sfb, i, start, end; + FLOAT8 ATH_f; + FLOAT8 samp_freq = gfp->out_samplerate; + + for (sfb = 0; sfb < SBMAX_l; sfb++) { + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + ATH_l[sfb]=FLOAT8_MAX; + for (i = start ; i < end; i++) { + FLOAT8 freq = i*samp_freq/(2*576); + ATH_f = ATHmdct( gfp, freq ); /* freq in kHz */ + ATH_l[sfb] = Min( ATH_l[sfb], ATH_f ); + } + } + + for (sfb = 0; sfb < SBMAX_s; sfb++){ + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb+1 ]; + ATH_s[sfb] = FLOAT8_MAX; + for (i = start ; i < end; i++) { + FLOAT8 freq = i*samp_freq/(2*192); + ATH_f = ATHmdct( gfp, freq ); /* freq in kHz */ + ATH_s[sfb] = Min( ATH_s[sfb], ATH_f ); + } + } + + /* no-ATH mode: + * reduce ATH to -200 dB + */ + + if (gfp->noATH) { + for (sfb = 0; sfb < SBMAX_l; sfb++) { + ATH_l[sfb] = 1E-37; + } + for (sfb = 0; sfb < SBMAX_s; sfb++) { + ATH_s[sfb] = 1E-37; + } + } + + /* work in progress, don't rely on it too much + */ + gfc->ATH-> floor = 10. * log10( ATHmdct( gfp, -1. ) ); + + /* + { FLOAT8 g=10000, t=1e30, x; + for ( f = 100; f < 10000; f++ ) { + x = ATHmdct( gfp, f ); + if ( t > x ) t = x, g = f; + } + printf("min=%g\n", g); + }*/ +} + + + + + +/* convert from L/R <-> Mid/Side, src == dst allowed */ +void ms_convert(FLOAT8 dst[2][576], FLOAT8 src[2][576]) +{ + FLOAT8 l; + FLOAT8 r; + int i; + for (i = 0; i < 576; ++i) { + l = src[0][i]; + r = src[1][i]; + dst[0][i] = (l+r) * (FLOAT8)(SQRT2*0.5); + dst[1][i] = (l-r) * (FLOAT8)(SQRT2*0.5); + } +} + + + +/************************************************************************ + * allocate bits among 2 channels based on PE + * mt 6/99 + * bugfixes rh 8/01: often allocated more than the allowed 4095 bits + ************************************************************************/ +int on_pe( lame_global_flags *gfp, FLOAT8 pe[][2], III_side_info_t *l3_side, + int targ_bits[2], int mean_bits, int gr ) +{ + lame_internal_flags * gfc = gfp->internal_flags; + gr_info * cod_info; + int extra_bits, tbits, bits; + int add_bits[2]; + int max_bits; /* maximum allowed bits for this granule */ + int ch; + + /* allocate targ_bits for granule */ + ResvMaxBits( gfp, mean_bits, &tbits, &extra_bits ); + max_bits = tbits + extra_bits; + if (max_bits > MAX_BITS) /* hard limit per granule */ + max_bits = MAX_BITS; + + for ( bits = 0, ch = 0; ch < gfc->channels_out; ++ch ) { + /****************************************************************** + * allocate bits for each channel + ******************************************************************/ + cod_info = &l3_side->gr[gr].ch[ch].tt; + + targ_bits[ch] = Min( MAX_BITS, tbits/gfc->channels_out ); + + if (gfc->nsPsy.use) { + add_bits[ch] = targ_bits[ch] * pe[gr][ch] / 700.0 - targ_bits[ch]; + } + else { + add_bits[ch] = (pe[gr][ch]-750) / 1.4; + /* short blocks us a little extra, no matter what the pe */ + if ( cod_info->block_type == SHORT_TYPE ) { + if (add_bits[ch] < mean_bits/4) + add_bits[ch] = mean_bits/4; + } + } + + /* at most increase bits by 1.5*average */ + if (add_bits[ch] > mean_bits*3/4) + add_bits[ch] = mean_bits*3/4; + if (add_bits[ch] < 0) + add_bits[ch] = 0; + + if (add_bits[ch]+targ_bits[ch] > MAX_BITS) + add_bits[ch] = Max( 0, MAX_BITS-targ_bits[ch] ); + + bits += add_bits[ch]; + } + if (bits > extra_bits) { + for ( ch = 0; ch < gfc->channels_out; ++ch ) { + add_bits[ch] = extra_bits * add_bits[ch] / bits; + } + } + + for ( ch = 0; ch < gfc->channels_out; ++ch ) { + targ_bits[ch] += add_bits[ch]; + extra_bits -= add_bits[ch]; + assert( targ_bits[ch] <= MAX_BITS ); + } + assert( max_bits <= MAX_BITS ); + return max_bits; +} + + + + +void reduce_side(int targ_bits[2],FLOAT8 ms_ener_ratio,int mean_bits,int max_bits) +{ + int move_bits; + FLOAT fac; + + + /* ms_ener_ratio = 0: allocate 66/33 mid/side fac=.33 + * ms_ener_ratio =.5: allocate 50/50 mid/side fac= 0 */ + /* 75/25 split is fac=.5 */ + /* float fac = .50*(.5-ms_ener_ratio[gr])/.5;*/ + fac = .33*(.5-ms_ener_ratio)/.5; + if (fac<0) fac=0; + if (fac>.5) fac=.5; + + /* number of bits to move from side channel to mid channel */ + /* move_bits = fac*targ_bits[1]; */ + move_bits = fac*.5*(targ_bits[0]+targ_bits[1]); + + if (move_bits > MAX_BITS - targ_bits[0]) { + move_bits = MAX_BITS - targ_bits[0]; + } + if (move_bits<0) move_bits=0; + + if (targ_bits[1] >= 125) { + /* dont reduce side channel below 125 bits */ + if (targ_bits[1]-move_bits > 125) { + + /* if mid channel already has 2x more than average, dont bother */ + /* mean_bits = bits per granule (for both channels) */ + if (targ_bits[0] < mean_bits) + targ_bits[0] += move_bits; + targ_bits[1] -= move_bits; + } else { + targ_bits[0] += targ_bits[1] - 125; + targ_bits[1] = 125; + } + } + + move_bits=targ_bits[0]+targ_bits[1]; + if (move_bits > max_bits) { + targ_bits[0]=(max_bits*targ_bits[0])/move_bits; + targ_bits[1]=(max_bits*targ_bits[1])/move_bits; + } + assert (targ_bits[0] <= MAX_BITS); + assert (targ_bits[1] <= MAX_BITS); +} + + +/** + * Robert Hegemann 2001-04-27: + * this adjusts the ATH, keeping the original noise floor + * affects the higher frequencies more than the lower ones + */ + +FLOAT8 athAdjust( FLOAT8 a, FLOAT8 x, FLOAT8 athFloor ) +{ + /* work in progress + */ + FLOAT8 const o = 90.30873362; + FLOAT8 const p = 94.82444863; + FLOAT8 u = 10. * log10(x); + FLOAT8 v = a*a; + FLOAT8 w = 0.0; + u -= athFloor; // undo scaling + if ( v > 1E-20 ) w = 1. + 10. * log10(v) / o; + if ( w < 0 ) w = 0.; + u *= w; + u += athFloor + o-p; // redo scaling + + return pow( 10., 0.1*u ); +} + + +/*************************************************************************/ +/* calc_xmin */ +/*************************************************************************/ + +/* + Calculate the allowed distortion for each scalefactor band, + as determined by the psychoacoustic model. + xmin(sb) = ratio(sb) * en(sb) / bw(sb) + + returns number of sfb's with energy > ATH +*/ +int calc_xmin( + lame_global_flags *gfp, + const FLOAT8 xr [576], + const III_psy_ratio * const ratio, + const gr_info * const cod_info, + III_psy_xmin * const l3_xmin ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int sfb,j,start, end, bw,l, b, ath_over=0; + FLOAT8 en0, xmin, ener, tmpATH; + ATH_t * ATH = gfc->ATH; + + if (cod_info->block_type == SHORT_TYPE) { + + for ( j = 0, sfb = 0; sfb < SBMAX_s; sfb++ ) { + if ( gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh ) + tmpATH = athAdjust( ATH->adjust, ATH->s[sfb], ATH->floor ); + else + tmpATH = ATH->adjust * ATH->s[sfb]; + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb + 1 ]; + bw = end - start; + + for ( b = 0; b < 3; b++ ) { + for (en0 = 0.0, l = start; l < end; l++) { + ener = xr[j++]; + ener = ener * ener; + en0 += ener; + } + en0 /= bw; + + if (gfp->ATHonly || gfp->ATHshort) { + xmin = tmpATH; + } + else { + xmin = ratio->en.s[sfb][b]; + if (xmin > 0.0) + xmin = en0 * ratio->thm.s[sfb][b] * gfc->masking_lower / xmin; + if (xmin < tmpATH) + xmin = tmpATH; + } + xmin *= bw; + + if (gfc->nsPsy.use) { + if (sfb <= 5) xmin *= gfc->nsPsy.bass; + else if (sfb <= 10) xmin *= gfc->nsPsy.alto; + else xmin *= gfc->nsPsy.treble; + if ((gfp->VBR == vbr_off || gfp->VBR == vbr_abr) && gfp->quality <= 1) + xmin *= 0.001; + } + l3_xmin->s[sfb][b] = xmin; + if (en0 > tmpATH) ath_over++; + } /* b */ + } /* sfb */ + + if (gfp->useTemporal) { + for (sfb = 0; sfb < SBMAX_s; sfb++ ) { + for ( b = 1; b < 3; b++ ) { + xmin = l3_xmin->s[sfb][b] * (1.0 - gfc->decay) + + l3_xmin->s[sfb][b-1] * gfc->decay; + if (l3_xmin->s[sfb][b] < xmin) + l3_xmin->s[sfb][b] = xmin; + } + } + } + + } /* end of short block case */ + else { + + for ( sfb = 0; sfb < SBMAX_l; sfb++ ){ + if ( gfp->VBR == vbr_rh || gfp->VBR == vbr_mtrh ) + tmpATH = athAdjust( ATH->adjust, ATH->l[sfb], ATH->floor ); + else + tmpATH = ATH->adjust * ATH->l[sfb]; + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + bw = end - start; + + for (en0 = 0.0, l = start; l < end; l++ ) { + ener = xr[l] * xr[l]; + en0 += ener; + } + /* why is it different from short blocks */ + if ( !gfc->nsPsy.use ) en0 /= bw; + + if (gfp->ATHonly) { + xmin = tmpATH; + } + else { + xmin = ratio->en.l[sfb]; + if (xmin > 0.0) + xmin = en0 * ratio->thm.l[sfb] * gfc->masking_lower / xmin; + if (xmin < tmpATH) + xmin = tmpATH; + } + /* why is it different from short blocks */ + if ( !gfc->nsPsy.use ) { + xmin *= bw; + } + else { + if (sfb <= 6) xmin *= gfc->nsPsy.bass; + else if (sfb <= 13) xmin *= gfc->nsPsy.alto; + else if (sfb <= 20) xmin *= gfc->nsPsy.treble; + else xmin *= gfc->nsPsy.sfb21; + if ((gfp->VBR == vbr_off || gfp->VBR == vbr_abr) && gfp->quality <= 1) + xmin *= 0.001; + } + l3_xmin->l[sfb] = xmin; + if (en0 > tmpATH) ath_over++; + } /* sfb */ + + } /* end of long block case */ + + return ath_over; +} + + + + + + + +/*************************************************************************/ +/* calc_noise */ +/*************************************************************************/ + +// -oo dB => -1.00 +// - 6 dB => -0.97 +// - 3 dB => -0.80 +// - 2 dB => -0.64 +// - 1 dB => -0.38 +// 0 dB => 0.00 +// + 1 dB => +0.49 +// + 2 dB => +1.06 +// + 3 dB => +1.68 +// + 6 dB => +3.69 +// +10 dB => +6.45 + +double penalties ( double noise ) +{ + return log ( 0.368 + 0.632 * noise * noise * noise ); +} + +/* mt 5/99: Function: Improved calc_noise for a single channel */ + +int calc_noise( + const lame_internal_flags * const gfc, + const FLOAT8 xr [576], + const int ix [576], + const gr_info * const cod_info, + const III_psy_xmin * const l3_xmin, + const III_scalefac_t * const scalefac, + III_psy_xmin * xfsf, + calc_noise_result * const res ) +{ + int sfb,start, end, j,l, i, over=0; + FLOAT8 sum; + + int count=0; + FLOAT8 noise,noise_db; + FLOAT8 over_noise_db = 0; + FLOAT8 tot_noise_db = 0; /* 0 dB relative to masking */ + FLOAT8 max_noise = 1E-20; /* -200 dB relative to masking */ + double klemm_noise = 1E-37; + + if (cod_info->block_type == SHORT_TYPE) { + int max_index = gfc->sfb21_extra ? SBMAX_s : SBPSY_s; + + for ( j=0, sfb = 0; sfb < max_index; sfb++ ) { + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb+1 ]; + for ( i = 0; i < 3; i++ ) { + FLOAT8 step; + int s; + + s = (scalefac->s[sfb][i] << (cod_info->scalefac_scale + 1)) + + cod_info->subblock_gain[i] * 8; + s = cod_info->global_gain - s; + + assert(s=0); + step = POW20(s); + sum = 0.0; + l = start; + do { + FLOAT8 temp; + temp = pow43[ix[j]]; + temp *= step; + temp -= fabs(xr[j]); + ++j; + sum += temp * temp; + l++; + } while (l < end); + noise = xfsf->s[sfb][i] = sum / l3_xmin->s[sfb][i]; + + max_noise = Max(max_noise,noise); + klemm_noise += penalties (noise); + + noise_db=10*log10(Max(noise,1E-20)); + tot_noise_db += noise_db; + + if (noise > 1) { + over++; + over_noise_db += noise_db; + } + count++; + } + } + }else{ /* cod_info->block_type == SHORT_TYPE */ + int max_index = gfc->sfb21_extra ? SBMAX_l : SBPSY_l; + + for ( sfb = 0; sfb < max_index; sfb++ ) { + FLOAT8 step; + int s = scalefac->l[sfb]; + + if (cod_info->preflag) + s += pretab[sfb]; + + s = cod_info->global_gain - (s << (cod_info->scalefac_scale + 1)); + assert(s=0); + step = POW20(s); + + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + + for ( sum = 0.0, l = start; l < end; l++ ) { + FLOAT8 temp; + temp = fabs(xr[l]) - pow43[ix[l]] * step; + sum += temp * temp; + } + noise = xfsf->l[sfb] = sum / l3_xmin->l[sfb]; + max_noise=Max(max_noise,noise); + klemm_noise += penalties (noise); + + noise_db=10*log10(Max(noise,1E-20)); + /* multiplying here is adding in dB, but can overflow */ + //tot_noise *= Max(noise, 1E-20); + tot_noise_db += noise_db; + + if (noise > 1) { + over++; + /* multiplying here is adding in dB -but can overflow */ + //over_noise *= noise; + over_noise_db += noise_db; + } + + count++; + } + } /* cod_info->block_type == SHORT_TYPE */ + + /* normalization at this point by "count" is not necessary, since + * the values are only used to compare with previous values */ + res->over_count = over; + + /* convert to db. DO NOT CHANGE THESE */ + /* tot_noise = is really the average over each sfb of: + [noise(db) - allowed_noise(db)] + + and over_noise is the same average, only over only the + bands with noise > allowed_noise. + + */ + + //res->tot_noise = 10.*log10(Max(1e-20,tot_noise )); + //res->over_noise = 10.*log10(Max(1e+00,over_noise)); + res->tot_noise = tot_noise_db; + res->over_noise = over_noise_db; + res->max_noise = 10.*log10(Max(1e-20,max_noise )); + res->klemm_noise = 10.*log10(Max(1e-20,klemm_noise)); + + return over; +} + + + + + + + + + + + + + + +/************************************************************************ + * + * set_pinfo() + * + * updates plotting data + * + * Mark Taylor 2000-??-?? + * + * Robert Hegemann: moved noise/distortion calc into it + * + ************************************************************************/ + +static +void set_pinfo ( + lame_global_flags *gfp, + const gr_info * const cod_info, + const III_psy_ratio * const ratio, + const III_scalefac_t * const scalefac, + const FLOAT8 xr[576], + const int l3_enc[576], + const int gr, + const int ch ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int sfb; + int j,i,l,start,end,bw; + FLOAT8 en0,en1; + FLOAT ifqstep = ( cod_info->scalefac_scale == 0 ) ? .5 : 1.0; + + + III_psy_xmin l3_xmin; + calc_noise_result noise; + III_psy_xmin xfsf; + + calc_xmin (gfp,xr, ratio, cod_info, &l3_xmin); + + calc_noise (gfc, xr, l3_enc, cod_info, &l3_xmin, scalefac, &xfsf, &noise); + + if (cod_info->block_type == SHORT_TYPE) { + for (j=0, sfb = 0; sfb < SBMAX_s; sfb++ ) { + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb + 1 ]; + bw = end - start; + for ( i = 0; i < 3; i++ ) { + for ( en0 = 0.0, l = start; l < end; l++ ) { + en0 += xr[j] * xr[j]; + ++j; + } + en0=Max(en0/bw,1e-20); + + +#if 0 +{ + double tot1,tot2; + if (sfben.s[sfb][i]; + + DEBUGF("%i %i sfb=%i mdct=%f fft=%f fft-mdct=%f db \n", + gr,ch,sfb, + 10*log10(Max(1e-25,ratio->en.s[sfb][i])), + 10*log10(Max(1e-25,en0)), + 10*log10((Max(1e-25,en0)/Max(1e-25,ratio->en.s[sfb][i])))); + + if (sfb==SBMAX_s-2) { + DEBUGF("%i %i toti %f %f ratio=%f db \n",gr,ch, + 10*log10(Max(1e-25,tot2)), + 10*log(Max(1e-25,tot1)), + 10*log10(Max(1e-25,tot1)/(Max(1e-25,tot2)))); + + } + } + /* + masking: multiplied by en0/fft_energy + average seems to be about -135db. + */ +} +#endif + + + /* convert to MDCT units */ + en1=1e15; /* scaling so it shows up on FFT plot */ + gfc->pinfo->xfsf_s[gr][ch][3*sfb+i] + = en1*xfsf.s[sfb][i]*l3_xmin.s[sfb][i]/bw; + gfc->pinfo->en_s[gr][ch][3*sfb+i] = en1*en0; + + if (ratio->en.s[sfb][i]>0) + en0 = en0/ratio->en.s[sfb][i]; + else + en0=0; + if (gfp->ATHonly || gfp->ATHshort) + en0=0; + + gfc->pinfo->thr_s[gr][ch][3*sfb+i] = + en1*Max(en0*ratio->thm.s[sfb][i],gfc->ATH->s[sfb]); + + + /* there is no scalefactor bands >= SBPSY_s */ + if (sfb < SBPSY_s) { + gfc->pinfo->LAMEsfb_s[gr][ch][3*sfb+i]= + -ifqstep*scalefac->s[sfb][i]; + } else { + gfc->pinfo->LAMEsfb_s[gr][ch][3*sfb+i]=0; + } + gfc->pinfo->LAMEsfb_s[gr][ch][3*sfb+i] -= + 2*cod_info->subblock_gain[i]; + } + } + } else { + for ( sfb = 0; sfb < SBMAX_l; sfb++ ) { + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + bw = end - start; + for ( en0 = 0.0, l = start; l < end; l++ ) + en0 += xr[l] * xr[l]; + if (!gfc->nsPsy.use) en0/=bw; + /* + DEBUGF("diff = %f \n",10*log10(Max(ratio[gr][ch].en.l[sfb],1e-20)) + -(10*log10(en0)+150)); + */ + +#if 0 + { + double tot1,tot2; + if (sfb==0) { + tot1=0; + tot2=0; + } + tot1 += en0; + tot2 += ratio->en.l[sfb]; + + + DEBUGF("%i %i sfb=%i mdct=%f fft=%f fft-mdct=%f db \n", + gr,ch,sfb, + 10*log10(Max(1e-25,ratio->en.l[sfb])), + 10*log10(Max(1e-25,en0)), + 10*log10((Max(1e-25,en0)/Max(1e-25,ratio->en.l[sfb])))); + + if (sfb==SBMAX_l-1) { + DEBUGF("%i %i toti %f %f ratio=%f db \n", + gr,ch, + 10*log10(Max(1e-25,tot2)), + 10*log(Max(1e-25,tot1)), + 10*log10(Max(1e-25,tot1)/(Max(1e-25,tot2)))); + } + /* + masking: multiplied by en0/fft_energy + average seems to be about -147db. + */ +} +#endif + + + /* convert to MDCT units */ + en1=1e15; /* scaling so it shows up on FFT plot */ + gfc->pinfo->xfsf[gr][ch][sfb] = en1*xfsf.l[sfb]*l3_xmin.l[sfb]/bw; + gfc->pinfo->en[gr][ch][sfb] = en1*en0; + if (ratio->en.l[sfb]>0) + en0 = en0/ratio->en.l[sfb]; + else + en0=0; + if (gfp->ATHonly) + en0=0; + gfc->pinfo->thr[gr][ch][sfb] = + en1*Max(en0*ratio->thm.l[sfb],gfc->ATH->l[sfb]); + + /* there is no scalefactor bands >= SBPSY_l */ + if (sfbl[sfb]<0) /* scfsi! */ + gfc->pinfo->LAMEsfb[gr][ch][sfb] = + gfc->pinfo->LAMEsfb[0][ch][sfb]; + else + gfc->pinfo->LAMEsfb[gr][ch][sfb] = -ifqstep*scalefac->l[sfb]; + }else{ + gfc->pinfo->LAMEsfb[gr][ch][sfb] = 0; + } + + if (cod_info->preflag && sfb>=11) + gfc->pinfo->LAMEsfb[gr][ch][sfb] -= ifqstep*pretab[sfb]; + } /* for sfb */ + } /* block type long */ + gfc->pinfo->LAMEqss [gr][ch] = cod_info->global_gain; + gfc->pinfo->LAMEmainbits[gr][ch] = cod_info->part2_3_length; + gfc->pinfo->LAMEsfbits [gr][ch] = cod_info->part2_length; + + gfc->pinfo->over [gr][ch] = noise.over_count; + gfc->pinfo->max_noise [gr][ch] = noise.max_noise; + gfc->pinfo->over_noise[gr][ch] = noise.over_noise; + gfc->pinfo->tot_noise [gr][ch] = noise.tot_noise; +} + + +/************************************************************************ + * + * set_frame_pinfo() + * + * updates plotting data for a whole frame + * + * Robert Hegemann 2000-10-21 + * + ************************************************************************/ + +void set_frame_pinfo( + lame_global_flags *gfp, + FLOAT8 xr [2][2][576], + III_psy_ratio ratio [2][2], + int l3_enc [2][2][576], + III_scalefac_t scalefac [2][2] ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + unsigned int sfb; + int ch; + int gr; + int act_l3enc[576]; + III_scalefac_t act_scalefac [2]; + int scsfi[2] = {0,0}; + + + gfc->masking_lower = 1.0; + + /* reconstruct the scalefactors in case SCSFI was used + */ + for (ch = 0; ch < gfc->channels_out; ch ++) { + for (sfb = 0; sfb < SBMAX_l; sfb ++) { + if (scalefac[1][ch].l[sfb] == -1) {/* scfsi */ + act_scalefac[ch].l[sfb] = scalefac[0][ch].l[sfb]; + scsfi[ch] = 1; + } else { + act_scalefac[ch].l[sfb] = scalefac[1][ch].l[sfb]; + } + } + } + + /* for every granule and channel patch l3_enc and set info + */ + for (gr = 0; gr < gfc->mode_gr; gr ++) { + for (ch = 0; ch < gfc->channels_out; ch ++) { + int i; + gr_info *cod_info = &gfc->l3_side.gr[gr].ch[ch].tt; + + /* revert back the sign of l3enc */ + for ( i = 0; i < 576; i++) { + if (xr[gr][ch][i] < 0) + act_l3enc[i] = -l3_enc[gr][ch][i]; + else + act_l3enc[i] = +l3_enc[gr][ch][i]; + } + if (gr == 1 && scsfi[ch]) + set_pinfo (gfp, cod_info, &ratio[gr][ch], &act_scalefac[ch], + xr[gr][ch], act_l3enc, gr, ch); + else + set_pinfo (gfp, cod_info, &ratio[gr][ch], &scalefac[gr][ch], + xr[gr][ch], act_l3enc, gr, ch); + } /* for ch */ + } /* for gr */ +} + + + + +/********************************************************************* + * nonlinear quantization of xr + * More accurate formula than the ISO formula. Takes into account + * the fact that we are quantizing xr -> ix, but we want ix^4/3 to be + * as close as possible to x^4/3. (taking the nearest int would mean + * ix is as close as possible to xr, which is different.) + * From Segher Boessenkool 11/1999 + * ASM optimization from + * Mathew Hendry 11/1999 + * Acy Stapp 11/1999 + * Takehiro Tominaga 11/1999 + * 9/00: ASM code removed in favor of IEEE754 hack. If you need + * the ASM code, check CVS circa Aug 2000. + *********************************************************************/ + + +#ifdef TAKEHIRO_IEEE754_HACK + +typedef union { + float f; + int i; +} fi_union; + +#define MAGIC_FLOAT (65536*(128)) +#define MAGIC_INT 0x4b000000 + +void quantize_xrpow(const FLOAT8 *xp, int *pi, FLOAT8 istep) +{ + /* quantize on xr^(3/4) instead of xr */ + int j; + fi_union *fi; + + fi = (fi_union *)pi; + for (j = 576 / 4 - 1; j >= 0; --j) { + double x0 = istep * xp[0]; + double x1 = istep * xp[1]; + double x2 = istep * xp[2]; + double x3 = istep * xp[3]; + + x0 += MAGIC_FLOAT; fi[0].f = x0; + x1 += MAGIC_FLOAT; fi[1].f = x1; + x2 += MAGIC_FLOAT; fi[2].f = x2; + x3 += MAGIC_FLOAT; fi[3].f = x3; + + fi[0].f = x0 + (adj43asm - MAGIC_INT)[fi[0].i]; + fi[1].f = x1 + (adj43asm - MAGIC_INT)[fi[1].i]; + fi[2].f = x2 + (adj43asm - MAGIC_INT)[fi[2].i]; + fi[3].f = x3 + (adj43asm - MAGIC_INT)[fi[3].i]; + + fi[0].i -= MAGIC_INT; + fi[1].i -= MAGIC_INT; + fi[2].i -= MAGIC_INT; + fi[3].i -= MAGIC_INT; + fi += 4; + xp += 4; + } +} + +# define ROUNDFAC -0.0946 +void quantize_xrpow_ISO(const FLOAT8 *xp, int *pi, FLOAT8 istep) +{ + /* quantize on xr^(3/4) instead of xr */ + int j; + fi_union *fi; + + fi = (fi_union *)pi; + for (j=576/4 - 1;j>=0;j--) { + fi[0].f = istep * xp[0] + (ROUNDFAC + MAGIC_FLOAT); + fi[1].f = istep * xp[1] + (ROUNDFAC + MAGIC_FLOAT); + fi[2].f = istep * xp[2] + (ROUNDFAC + MAGIC_FLOAT); + fi[3].f = istep * xp[3] + (ROUNDFAC + MAGIC_FLOAT); + + fi[0].i -= MAGIC_INT; + fi[1].i -= MAGIC_INT; + fi[2].i -= MAGIC_INT; + fi[3].i -= MAGIC_INT; + fi+=4; + xp+=4; + } +} + +#else + +/********************************************************************* + * XRPOW_FTOI is a macro to convert floats to ints. + * if XRPOW_FTOI(x) = nearest_int(x), then QUANTFAC(x)=adj43asm[x] + * ROUNDFAC= -0.0946 + * + * if XRPOW_FTOI(x) = floor(x), then QUANTFAC(x)=asj43[x] + * ROUNDFAC=0.4054 + * + * Note: using floor() or (int) is extermely slow. On machines where + * the TAKEHIRO_IEEE754_HACK code above does not work, it is worthwile + * to write some ASM for XRPOW_FTOI(). + *********************************************************************/ +#define XRPOW_FTOI(src,dest) ((dest) = (int)(src)) +#define QUANTFAC(rx) adj43[rx] +#define ROUNDFAC 0.4054 + + +void quantize_xrpow(const FLOAT8 *xr, int *ix, FLOAT8 istep) { + /* quantize on xr^(3/4) instead of xr */ + /* from Wilfried.Behne@t-online.de. Reported to be 2x faster than + the above code (when not using ASM) on PowerPC */ + int j; + + for ( j = 576/8; j > 0; --j) { + FLOAT8 x1, x2, x3, x4, x5, x6, x7, x8; + int rx1, rx2, rx3, rx4, rx5, rx6, rx7, rx8; + x1 = *xr++ * istep; + x2 = *xr++ * istep; + XRPOW_FTOI(x1, rx1); + x3 = *xr++ * istep; + XRPOW_FTOI(x2, rx2); + x4 = *xr++ * istep; + XRPOW_FTOI(x3, rx3); + x5 = *xr++ * istep; + XRPOW_FTOI(x4, rx4); + x6 = *xr++ * istep; + XRPOW_FTOI(x5, rx5); + x7 = *xr++ * istep; + XRPOW_FTOI(x6, rx6); + x8 = *xr++ * istep; + XRPOW_FTOI(x7, rx7); + x1 += QUANTFAC(rx1); + XRPOW_FTOI(x8, rx8); + x2 += QUANTFAC(rx2); + XRPOW_FTOI(x1,*ix++); + x3 += QUANTFAC(rx3); + XRPOW_FTOI(x2,*ix++); + x4 += QUANTFAC(rx4); + XRPOW_FTOI(x3,*ix++); + x5 += QUANTFAC(rx5); + XRPOW_FTOI(x4,*ix++); + x6 += QUANTFAC(rx6); + XRPOW_FTOI(x5,*ix++); + x7 += QUANTFAC(rx7); + XRPOW_FTOI(x6,*ix++); + x8 += QUANTFAC(rx8); + XRPOW_FTOI(x7,*ix++); + XRPOW_FTOI(x8,*ix++); + } +} + + + + + + +void quantize_xrpow_ISO( const FLOAT8 *xr, int *ix, FLOAT8 istep ) +{ + /* quantize on xr^(3/4) instead of xr */ + const FLOAT8 compareval0 = (1.0 - 0.4054)/istep; + int j; + /* depending on architecture, it may be worth calculating a few more + compareval's. + + eg. compareval1 = (2.0 - 0.4054/istep); + .. and then after the first compare do this ... + if compareval1>*xr then ix = 1; + + On a pentium166, it's only worth doing the one compare (as done here), + as the second compare becomes more expensive than just calculating + the value. Architectures with slow FP operations may want to add some + more comparevals. try it and send your diffs statistically speaking + + 73% of all xr*istep values give ix=0 + 16% will give 1 + 4% will give 2 + */ + for (j=576;j>0;j--) { + if (compareval0 > *xr) { + *(ix++) = 0; + xr++; + } else { + /* *(ix++) = (int)( istep*(*(xr++)) + 0.4054); */ + XRPOW_FTOI( istep*(*(xr++)) + ROUNDFAC , *(ix++) ); + } + } +} + +#endif diff --git a/lib/lame/quantize_pvt.h b/lib/lame/quantize_pvt.h new file mode 100644 index 0000000..79e7a5a --- /dev/null +++ b/lib/lame/quantize_pvt.h @@ -0,0 +1,124 @@ +/* + * quantize_pvt include file + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_QUANTIZE_PVT_H +#define LAME_QUANTIZE_PVT_H + +#include "l3side.h" +#define IXMAX_VAL 8206 /* ix always <= 8191+15. see count_bits() */ + +/* buggy Winamp decoder cannot handle values > 8191 */ +/* #define IXMAX_VAL 8191 */ + +#define PRECALC_SIZE (IXMAX_VAL+2) + + +extern const int nr_of_sfb_block[6][3][4]; +extern const char pretab[SBMAX_l]; +extern const char slen1_tab[16]; +extern const char slen2_tab[16]; + +extern const scalefac_struct sfBandIndex[9]; + +extern FLOAT8 pow43[PRECALC_SIZE]; +extern FLOAT8 adj43[PRECALC_SIZE]; +extern FLOAT8 adj43asm[PRECALC_SIZE]; + +#define Q_MAX 330 + +extern FLOAT8 pow20[Q_MAX]; +extern FLOAT8 ipow20[Q_MAX]; +extern FLOAT8 *iipow20_; + +typedef struct calc_noise_result_t { + int over_count; /* number of quantization noise > masking */ + FLOAT8 over_noise; /* sum of quantization noise > masking */ + FLOAT8 tot_noise; /* sum of all quantization noise */ + FLOAT8 max_noise; /* max quantization noise */ + float klemm_noise; +} calc_noise_result; + +void compute_ath (lame_global_flags * gfp, FLOAT8 ATH_l[SBPSY_l], + FLOAT8 ATH_s[SBPSY_l]); + +void ms_convert (FLOAT8 xr[2][576], FLOAT8 xr_org[2][576]); + +int on_pe (lame_global_flags *gfp, FLOAT8 pe[2][2], III_side_info_t * l3_side, + int targ_bits[2], int mean_bits, int gr); + +void reduce_side (int targ_bits[2], FLOAT8 ms_ener_ratio, int mean_bits, + int max_bits); + + +int bin_search_StepSize (lame_internal_flags * const gfc, gr_info * const cod_info, + const int desired_rate, const int start, + const FLOAT8 xrpow[576], int l3enc[576]); + +int inner_loop (lame_internal_flags * const gfc, gr_info * const cod_info, const int max_bits, + const FLOAT8 xrpow[576], int l3enc[576]); + +void iteration_init (lame_global_flags *gfp); + + +int calc_xmin (lame_global_flags *gfp, const FLOAT8 xr[576], + const III_psy_ratio * const ratio, const gr_info * const cod_info, + III_psy_xmin * const l3_xmin); + +int calc_noise (const lame_internal_flags * const gfc, const FLOAT8 xr[576], + const int ix[576], const gr_info * const cod_info, + const III_psy_xmin * const l3_xmin, + const III_scalefac_t * const scalefac, + III_psy_xmin * distort, calc_noise_result * const res); + +void set_frame_pinfo (lame_global_flags *gfp, FLOAT8 xr[2][2][576], + III_psy_ratio ratio[2][2], int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2]); + + +void quantize_xrpow (const FLOAT8 *xr, int *ix, FLOAT8 istep); + +void quantize_xrpow_ISO (const FLOAT8 *xr, int *ix, FLOAT8 istep); + + + +/* takehiro.c */ + +int count_bits (lame_internal_flags * const gfc, int * const ix, const FLOAT8 * const xr, + gr_info * const cod_info); + + +void best_huffman_divide (const lame_internal_flags * const gfc, + gr_info * const cod_info, int * const ix); + +void best_scalefac_store (const lame_internal_flags * gfc, const int gr, const int ch, + int l3_enc[2][2][576], III_side_info_t * const l3_side, + III_scalefac_t scalefac[2][2]); + +int scale_bitcount (III_scalefac_t * const scalefac, gr_info * const cod_info); + +int scale_bitcount_lsf (const lame_internal_flags *gfp, const III_scalefac_t * const scalefac, + gr_info * const cod_info); + +void huffman_init (lame_internal_flags * const gfc); + +#define LARGE_BITS 100000 + +#endif /* LAME_QUANTIZE_PVT_H */ diff --git a/lib/lame/reservoir.c b/lib/lame/reservoir.c new file mode 100644 index 0000000..38d3849 --- /dev/null +++ b/lib/lame/reservoir.c @@ -0,0 +1,288 @@ +/* + * bit reservoir source file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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: reservoir.c,v 1.1 2002/04/28 17:30:27 kramm Exp $ */ + +#include "config_static.h" + +#include +#include "util.h" +#include "reservoir.h" + +#ifdef WITH_DMALLOC +#include +#endif + +/* + ResvFrameBegin: + Called (repeatedly) at the beginning of a frame. Updates the maximum + size of the reservoir, and checks to make sure main_data_begin + was set properly by the formatter +*/ + +/* + * Background information: + * + * This is the original text from the ISO standard. Because of + * sooo many bugs and irritations correcting comments are added + * in brackets []. A '^W' means you should remove the last word. + * + * 1) The following rule can be used to calculate the maximum + * number of bits used for one granule [^W frame]: + * At the highest possible bitrate of Layer III (320 kbps + * per stereo signal [^W^W^W], 48 kHz) the frames must be of + * [^W^W^W are designed to have] constant length, i.e. + * one buffer [^W^W the frame] length is: + * + * 320 kbps * 1152/48 kHz = 7680 bit = 960 byte + * + * This value is used as the maximum buffer per channel [^W^W] at + * lower bitrates [than 320 kbps]. At 64 kbps mono or 128 kbps + * stereo the main granule length is 64 kbps * 576/48 kHz = 768 bit + * [per granule and channel] at 48 kHz sampling frequency. + * This means that there is a maximum deviation (short time buffer + * [= reservoir]) of 7680 - 2*2*768 = 4608 bits is allowed at 64 kbps. + * The actual deviation is equal to the number of bytes [with the + * meaning of octets] denoted by the main_data_end offset pointer. + * The actual maximum deviation is (2^9-1)*8 bit = 4088 bits + * [for MPEG-1 and (2^8-1)*8 bit for MPEG-2, both are hard limits]. + * ... The xchange of buffer bits between the left and right channel + * is allowed without restrictions [exception: dual channel]. + * Because of the [constructed] constraint on the buffer size + * main_data_end is always set to 0 in the case of bit_rate_index==14, + * i.e. data rate 320 kbps per stereo signal [^W^W^W]. In this case + * all data are allocated between adjacent header [^W sync] words + * [, i.e. there is no buffering at all]. + */ + +int +ResvFrameBegin(lame_global_flags *gfp,III_side_info_t *l3_side, int mean_bits, int frameLength ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int fullFrameBits; + int resvLimit; + int maxmp3buf; + +/* + * Meaning of the variables: + * resvLimit: (0, 8, ..., 8*255 (MPEG-2), 8*511 (MPEG-1)) + * Number of bits can be stored in previous frame(s) due to + * counter size constaints + * maxmp3buf: ( ??? ... 8*1951 (MPEG-1 and 2), 8*2047 (MPEG-2.5)) + * Number of bits allowed to encode one frame (you can take 8*511 bit + * from the bit reservoir and at most 8*1440 bit from the current + * frame (320 kbps, 32 kHz), so 8*1951 bit is the largest possible + * value for MPEG-1 and -2) + * + * maximum allowed granule/channel size times 4 = 8*2047 bits., + * so this is the absolute maximum supported by the format. + * + * + * fullFrameBits: maximum number of bits available for encoding + * the current frame. + * + * mean_bits: target number of bits per granule. + * + * frameLength: + * + * gfc->ResvMax: maximum allowed reservoir + * + * gfc->ResvSize: current reservoir size + * + * l3_side->resvDrain_pre: + * ancillary data to be added to previous frame: + * (only usefull in VBR modes if it is possible to have + * maxmp3buf < fullFrameBits)). Currently disabled, + * see #define NEW_DRAIN + * + * l3_side->resvDrain_post: + * ancillary data to be added to this frame: + * + */ + + /* main_data_begin has 9 bits in MPEG-1, 8 bits MPEG-2 */ + resvLimit = (gfp->version==1) ? 8*511 : 8*255 ; + + + /* maximum allowed frame size. dont use more than this number of + bits, even if the frame has the space for them: */ + /* Bouvigne suggests this more lax interpretation of the ISO doc + instead of using 8*960. */ + if (gfp->strict_ISO) { + if (gfp->version==1) + maxmp3buf=8*((int)(320000/(gfp->out_samplerate / (FLOAT8)1152)/8 +.5)); + else + maxmp3buf=8*((int)(160000/(gfp->out_samplerate / (FLOAT8)576)/8 +.5)); + } else + /*all mp3 decoders should have enough buffer to handle this value: size of a 320kbps 32kHz frame*/ + maxmp3buf = 8*1440; + + + if ( frameLength > maxmp3buf || gfp->disable_reservoir ) { + gfc->ResvMax = 0; + } else { + gfc->ResvMax = maxmp3buf - frameLength; + if ( gfc->ResvMax > resvLimit ) + gfc->ResvMax = resvLimit; + } + + fullFrameBits = mean_bits * gfc->mode_gr + Min ( gfc->ResvSize, gfc->ResvMax ); + + if ( fullFrameBits > maxmp3buf ) + fullFrameBits = maxmp3buf; + + assert ( 0 == gfc->ResvMax % 8 ); + assert ( gfc->ResvMax >= 0 ); + + l3_side->resvDrain_pre = 0; + + if ( gfc->pinfo != NULL ) { + gfc->pinfo->mean_bits = mean_bits / 2; /* expected bits per channel per granule [is this also right for mono/stereo, MPEG-1/2 ?] */ + gfc->pinfo->resvsize = gfc->ResvSize; + } + + return fullFrameBits; +} + + +/* + ResvMaxBits + returns targ_bits: target number of bits to use for 1 granule + extra_bits: amount extra available from reservoir + Mark Taylor 4/99 +*/ +void ResvMaxBits(lame_global_flags *gfp, int mean_bits, int *targ_bits, int *extra_bits) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int add_bits; + int full_fac; + + *targ_bits = mean_bits ; + + /* extra bits if the reservoir is almost full */ + full_fac=9; + if (gfc->ResvSize > ((gfc->ResvMax * full_fac) / 10)) { + add_bits= gfc->ResvSize-((gfc->ResvMax * full_fac) / 10); + *targ_bits += add_bits; + }else { + add_bits =0 ; + /* build up reservoir. this builds the reservoir a little slower + * than FhG. It could simple be mean_bits/15, but this was rigged + * to always produce 100 (the old value) at 128kbs */ + /* *targ_bits -= (int) (mean_bits/15.2);*/ + if (!gfp->disable_reservoir) + *targ_bits -= .1*mean_bits; + } + + + /* amount from the reservoir we are allowed to use. ISO says 6/10 */ + *extra_bits = + (gfc->ResvSize < (gfc->ResvMax*6)/10 ? gfc->ResvSize : (gfc->ResvMax*6)/10); + *extra_bits -= add_bits; + + if (*extra_bits < 0) *extra_bits=0; + + +} + +/* + ResvAdjust: + Called after a granule's bit allocation. Readjusts the size of + the reservoir to reflect the granule's usage. +*/ +void +ResvAdjust(lame_internal_flags *gfc,gr_info *gi, III_side_info_t *l3_side, int mean_bits ) +{ + gfc->ResvSize += (mean_bits / gfc->channels_out) - gi->part2_3_length; +#if 0 + printf("part2_3_length: %i avg=%i incres: %i resvsize=%i\n",gi->part2_3_length, + mean_bits/gfc->channels_out, +mean_bits/gfc->channels_out-gi->part2_3_length,gfc->ResvSize); +#endif +} + + +/* + ResvFrameEnd: + Called after all granules in a frame have been allocated. Makes sure + that the reservoir size is within limits, possibly by adding stuffing + bits. +*/ +void +ResvFrameEnd(lame_internal_flags *gfc, III_side_info_t *l3_side, int mean_bits) +{ + int stuffingBits; + int over_bits; + + + /* just in case mean_bits is odd, this is necessary... */ + if ( gfc->channels_out == 2 && (mean_bits & 1) ) + gfc->ResvSize += 1; + + stuffingBits=0; + l3_side->resvDrain_post = 0; + l3_side->resvDrain_pre = 0; + + /* we must be byte aligned */ + if ( (over_bits = gfc->ResvSize % 8) != 0 ) + stuffingBits += over_bits; + + + over_bits = (gfc->ResvSize - stuffingBits) - gfc->ResvMax; + if (over_bits > 0) { + assert ( 0 == over_bits % 8 ); + assert ( over_bits >= 0 ); + stuffingBits += over_bits; + } + + +#undef NEW_DRAIN +#ifdef NEW_DRAIN + /* drain as many bits as possible into previous frame ancillary data + * In particular, in VBR mode ResvMax may have changed, and we have + * to make sure main_data_begin does not create a reservoir bigger + * than ResvMax mt 4/00*/ + { + int mdb_bytes = Min(l3_side->main_data_begin*8,stuffingBits)/8; + l3_side->resvDrain_pre += 8*mdb_bytes; + stuffingBits -= 8*mdb_bytes; + gfc->ResvSize -= 8*mdb_bytes; + l3_side->main_data_begin -= mdb_bytes; + + + /* drain just enough to be byte aligned. The remaining bits will + * be added to the reservoir, and we will deal with them next frame. + * If the next frame is at a lower bitrate, it may have a larger ResvMax, + * and we will not have to waste these bits! mt 4/00 */ + assert ( stuffingBits >= 0 ); + l3_side->resvDrain_post += (stuffingBits % 8); + gfc->ResvSize -= stuffingBits % 8; + } +#else + /* drain the rest into this frames ancillary data*/ + l3_side->resvDrain_post += stuffingBits; + gfc->ResvSize -= stuffingBits; +#endif + + return; +} + + diff --git a/lib/lame/reservoir.h b/lib/lame/reservoir.h new file mode 100644 index 0000000..aeed917 --- /dev/null +++ b/lib/lame/reservoir.h @@ -0,0 +1,30 @@ +/* + * bit reservoir include file + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_RESERVOIR_H +#define LAME_RESERVOIR_H + +int ResvFrameBegin(lame_global_flags *gfp,III_side_info_t *l3_side, int mean_bits, int frameLength ); +void ResvMaxBits(lame_global_flags *gfp, int mean_bits, int *targ_bits, int *max_bits); +void ResvAdjust(lame_internal_flags *gfc,gr_info *gi, III_side_info_t *l3_side, int mean_bits ); +void ResvFrameEnd(lame_internal_flags *gfc,III_side_info_t *l3_side, int mean_bits ); + +#endif /* LAME_RESERVOIR_H */ diff --git a/lib/lame/set_get.c b/lib/lame/set_get.c new file mode 100644 index 0000000..5c04ca3 --- /dev/null +++ b/lib/lame/set_get.c @@ -0,0 +1,1550 @@ +/* -*- mode: C; mode: fold -*- */ +/* + * set/get functions for lame_global_flags + * + * Copyright (c) 2001 Alexander Leidinger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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: set_get.c,v 1.1 2002/04/28 17:30:28 kramm Exp $ */ + +#include "config_static.h" + +#include +#include "util.h" +#include "bitstream.h" /* because of compute_flushbits */ + +#ifdef WITH_DMALLOC +#include +#endif + + +/* + * input stream description + */ + +/* number of samples */ +/* it's unlikely for this function to return an error */ +int +lame_set_num_samples( lame_global_flags* gfp, + unsigned long num_samples) +{ + /* default = 2^32-1 */ + + gfp->num_samples = num_samples; + + return 0; +} + +unsigned long +lame_get_num_samples( const lame_global_flags* gfp ) +{ + return gfp->num_samples; +} + + +/* input samplerate */ +int +lame_set_in_samplerate( lame_global_flags* gfp, + int in_samplerate ) +{ + /* input sample rate in Hz, default = 44100 Hz */ + gfp->in_samplerate = in_samplerate; + + return 0; +} + +int +lame_get_in_samplerate( const lame_global_flags* gfp ) +{ + return gfp->in_samplerate; +} + + +/* number of channels in input stream */ +int +lame_set_num_channels( lame_global_flags* gfp, + int num_channels ) +{ + /* default = 2 */ + + if ( 2 < num_channels || 0 == num_channels ) + return -1; /* we don't support more than 2 channels */ + + gfp->num_channels = num_channels; + + return 0; +} + +int +lame_get_num_channels( const lame_global_flags* gfp ) +{ + return gfp->num_channels; +} + + +/* scale the input by this amount before encoding (not used for decoding) */ +int +lame_set_scale( lame_global_flags* gfp, + float scale ) +{ + /* default = 0 */ + gfp->scale = scale; + + return 0; +} + +float +lame_get_scale( const lame_global_flags* gfp ) +{ + return gfp->scale; +} + + +/* scale the channel 0 (left) input by this amount before + encoding (not used for decoding) */ +int +lame_set_scale_left( lame_global_flags* gfp, + float scale ) +{ + /* default = 0 */ + gfp->scale_left = scale; + + return 0; +} + +float +lame_get_scale_left( const lame_global_flags* gfp ) +{ + return gfp->scale_left; +} + + +/* scale the channel 1 (right) input by this amount before + encoding (not used for decoding) */ +int +lame_set_scale_right( lame_global_flags* gfp, + float scale ) +{ + /* default = 0 */ + gfp->scale_right = scale; + + return 0; +} + +float +lame_get_scale_right( const lame_global_flags* gfp ) +{ + return gfp->scale_right; +} + + +/* output sample rate in Hz */ +int +lame_set_out_samplerate( lame_global_flags* gfp, + int out_samplerate ) +{ + /* + * default = 0: LAME picks best value based on the amount + * of compression + * MPEG only allows: + * MPEG1 32, 44.1, 48khz + * MPEG2 16, 22.05, 24 + * MPEG2.5 8, 11.025, 12 + * + * (not used by decoding routines) + */ + gfp->out_samplerate = out_samplerate; + + return 0; +} + +int +lame_get_out_samplerate( const lame_global_flags* gfp ) +{ + return gfp->out_samplerate; +} + + + + +/* + * general control parameters + */ + +/* collect data for an MP3 frame analzyer */ +int +lame_set_analysis( lame_global_flags* gfp, + int analysis ) +{ + /* default = 0 */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > analysis || 1 < analysis ) + return -1; + + gfp->analysis = analysis; + + return 0; +} + +int +lame_get_analysis( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->analysis && 1 >= gfp->analysis ); + + return gfp->analysis; +} + + +/* write a Xing VBR header frame */ +int +lame_set_bWriteVbrTag( lame_global_flags* gfp, + int bWriteVbrTag ) +{ + /* default = 1 (on) for VBR/ABR modes, 0 (off) for CBR mode */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > bWriteVbrTag || 1 < bWriteVbrTag ) + return -1; + + gfp->bWriteVbrTag = bWriteVbrTag; + + return 0; +} + +int +lame_get_bWriteVbrTag( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->bWriteVbrTag && 1 >= gfp->bWriteVbrTag ); + + return gfp->bWriteVbrTag; +} + + + +/* decode only, use lame/mpglib to convert mp3/ogg to wav */ +int +lame_set_decode_only( lame_global_flags* gfp, + int decode_only ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > decode_only || 1 < decode_only ) + return -1; + + gfp->decode_only = decode_only; + + return 0; +} + +int +lame_get_decode_only( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->decode_only && 1 >= gfp->decode_only ); + + return gfp->decode_only; +} + + +/* encode a Vorbis .ogg file */ +int +lame_set_ogg( lame_global_flags* gfp, + int ogg ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > ogg || 1 < ogg ) + return -1; + + gfp->ogg = ogg; + + return 0; +} + +int +lame_get_ogg( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->ogg && 1 >= gfp->ogg ); + + return gfp->ogg; +} + + +/* + * Internal algorithm selection. + * True quality is determined by the bitrate but this variable will effect + * quality by selecting expensive or cheap algorithms. + * quality=0..9. 0=best (very slow). 9=worst. + * recommended: 2 near-best quality, not too slow + * 5 good quality, fast + * 7 ok quality, really fast + */ +int +lame_set_quality( lame_global_flags* gfp, + int quality ) +{ + gfp->quality = quality; + + return 0; +} + +int +lame_get_quality( const lame_global_flags* gfp ) +{ + return gfp->quality; +} + + +/* mode = STEREO, JOINT_STEREO, DUAL_CHANNEL (not supported), MONO */ +int +lame_set_mode( lame_global_flags* gfp, + MPEG_mode mode ) +{ + /* default: lame chooses based on compression ratio and input channels */ + + if( 0 > mode || MAX_INDICATOR <= mode ) + return -1; /* Unknown MPEG mode! */ + + gfp->mode = mode; + + return 0; +} + +MPEG_mode +lame_get_mode( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->mode && MAX_INDICATOR > gfp->mode ); + + return gfp->mode; +} + + +/* Us a M/S mode with a switching threshold based on compression ratio */ +int +lame_set_mode_automs( lame_global_flags* gfp, + int mode_automs ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > mode_automs || 1 < mode_automs ) + return -1; + + gfp->mode_automs = mode_automs; + + return 0; +} + +int +lame_get_mode_automs( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->mode_automs && 1 >= gfp->mode_automs ); + + return gfp->mode_automs; +} + + +/* + * Force M/S for all frames. For testing only. + * Requires mode = 1. + */ +int +lame_set_force_ms( lame_global_flags* gfp, + int force_ms ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > force_ms || 1 < force_ms ) + return -1; + + gfp->force_ms = force_ms; + + return 0; +} + +int +lame_get_force_ms( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->force_ms && 1 >= gfp->force_ms ); + + return gfp->force_ms; +} + + +/* Use free_format. */ +int +lame_set_free_format( lame_global_flags* gfp, + int free_format ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > free_format || 1 < free_format ) + return -1; + + gfp->free_format = free_format; + + return 0; +} + +int +lame_get_free_format( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->free_format && 1 >= gfp->free_format ); + + return gfp->free_format; +} + + +/* message handlers */ +int +lame_set_errorf( lame_global_flags* gfp, + void (*func)( const char*, va_list ) ) +{ + gfp->report.errorf = func; + + return 0; +} + +int +lame_set_debugf( lame_global_flags* gfp, + void (*func)( const char*, va_list ) ) +{ + gfp->report.debugf = func; + + return 0; +} + +int +lame_set_msgf( lame_global_flags* gfp, + void (*func)( const char *, va_list ) ) +{ + gfp->report.msgf = func; + + return 0; +} + + +/* + * Set one of + * - brate + * - compression ratio. + * + * Default is compression ratio of 11. + */ +int +lame_set_brate( lame_global_flags* gfp, + int brate ) +{ + gfp->brate = brate; + + return 0; +} + +int +lame_get_brate( const lame_global_flags* gfp ) +{ + return gfp->brate; +} + +int +lame_set_compression_ratio( lame_global_flags* gfp, + float compression_ratio ) +{ + gfp->compression_ratio = compression_ratio; + + return 0; +} + +float +lame_get_compression_ratio( const lame_global_flags* gfp ) +{ + return gfp->compression_ratio; +} + + + + +/* + * frame parameters + */ + +/* Mark as copyright protected. */ +int +lame_set_copyright( lame_global_flags* gfp, + int copyright ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > copyright || 1 < copyright ) + return -1; + + gfp->copyright = copyright; + + return 0; +} + +int +lame_get_copyright( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->copyright && 1 >= gfp->copyright ); + + return gfp->copyright; +} + + +/* Mark as original. */ +int +lame_set_original( lame_global_flags* gfp, + int original ) +{ + /* default = 1 (enabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > original || 1 < original ) + return -1; + + gfp->original = original; + + return 0; +} + +int +lame_get_original( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->original && 1 >= gfp->original ); + + return gfp->original; +} + + +/* + * error_protection. + * Use 2 bytes from each frame for CRC checksum. + */ +int +lame_set_error_protection( lame_global_flags* gfp, + int error_protection ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > error_protection || 1 < error_protection ) + return -1; + + gfp->error_protection = error_protection; + + return 0; +} + +int +lame_get_error_protection( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->error_protection && 1 >= gfp->error_protection ); + + return gfp->error_protection; +} + + +/* + * padding_type. + * PAD_NO = pad no frames + * PAD_ALL = pad all frames + * PAD_ADJUST = adjust padding + */ +int +lame_set_padding_type( lame_global_flags* gfp, + Padding_type padding_type ) +{ + /* default = 2 */ + + if ( 0 > padding_type || PAD_MAX_INDICATOR < padding_type ) + return -1; /* Unknown padding type */ + + gfp->padding_type = padding_type; + + return 0; +} + +Padding_type +lame_get_padding_type( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->padding_type && PAD_MAX_INDICATOR > gfp->padding_type ); + + return gfp->padding_type; +} + + +/* MP3 'private extension' bit. Meaningless. */ +int +lame_set_extension( lame_global_flags* gfp, + int extension ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > extension || 1 < extension ) + return -1; + + gfp->extension = extension; + + return 0; +} + +int +lame_get_extension( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->extension && 1 >= gfp->extension ); + + return gfp->extension; +} + + +/* Enforce strict ISO compliance. */ +int +lame_set_strict_ISO( lame_global_flags* gfp, + int strict_ISO ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > strict_ISO || 1 < strict_ISO ) + return -1; + + gfp->strict_ISO = strict_ISO; + + return 0; +} + +int +lame_get_strict_ISO( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->strict_ISO && 1 >= gfp->strict_ISO ); + + return gfp->strict_ISO; +} + + + + +/******************************************************************** + * quantization/noise shaping + ***********************************************************************/ + +/* Disable the bit reservoir. For testing only. */ +int +lame_set_disable_reservoir( lame_global_flags* gfp, + int disable_reservoir ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > disable_reservoir || 1 < disable_reservoir ) + return -1; + + gfp->disable_reservoir = disable_reservoir; + + return 0; +} + +int +lame_get_disable_reservoir( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->disable_reservoir && 1 >= gfp->disable_reservoir ); + + return gfp->disable_reservoir; +} + + + + +/* Select a different "best quantization" function. default = 0 */ +int +lame_set_experimentalX( lame_global_flags* gfp, + int experimentalX ) +{ + gfp->experimentalX = experimentalX; + + return 0; +} + +int +lame_get_experimentalX( const lame_global_flags* gfp ) +{ + return gfp->experimentalX; +} + + +/* Another experimental option. For testing only. */ +int +lame_set_experimentalY( lame_global_flags* gfp, + int experimentalY ) +{ + gfp->experimentalY = experimentalY; + + return 0; +} + +int +lame_get_experimentalY( const lame_global_flags* gfp ) +{ + return gfp->experimentalY; +} + + +/* Another experimental option. For testing only. */ +int +lame_set_experimentalZ( lame_global_flags* gfp, + int experimentalZ ) +{ + gfp->experimentalZ += experimentalZ; + + return 0; +} + +int +lame_get_experimentalZ( const lame_global_flags* gfp ) +{ + return gfp->experimentalZ; +} + + +/* Naoki's psycho acoustic model. */ +int +lame_set_exp_nspsytune( lame_global_flags* gfp, + int exp_nspsytune ) +{ + /* default = 0 (disabled) */ + + gfp->exp_nspsytune = exp_nspsytune; + + return 0; +} + +int +lame_get_exp_nspsytune( const lame_global_flags* gfp ) +{ + return gfp->exp_nspsytune; +} + + + + +/******************************************************************** + * VBR control + ***********************************************************************/ + +// Types of VBR. default = vbr_off = CBR +int +lame_set_VBR( lame_global_flags* gfp, + vbr_mode VBR ) +{ + if( 0 > VBR || vbr_max_indicator <= VBR ) + return -1; /* Unknown VBR mode! */ + + gfp->VBR = VBR; + + return 0; +} + +vbr_mode +lame_get_VBR( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->VBR && vbr_max_indicator > gfp->VBR ); + + return gfp->VBR; +} + + +/* + * VBR quality level. + * 0 = highest + * 9 = lowest + */ +int +lame_set_VBR_q( lame_global_flags* gfp, + int VBR_q ) +{ + /* XXX: This should be an enum */ + /* to whoever added this note: why should it be an enum? + do you want to call a specific setting by name? + say VBR quality level red? */ + /* No, but VBR_Q_HIGHEST, VBR_Q_HIGH, ..., VBR_Q_MID, ... + VBR_Q_LOW, VBR_Q_LOWEST (or something like that )and a + VBR_Q_DEFAULT, which aliases the default setting of + e.g. VBR_Q_MID. */ + + + if( 0 > VBR_q || 10 <= VBR_q ) + return -1; /* Unknown VBR quality level! */ + + gfp->VBR_q = VBR_q; + + return 0; +} + +int +lame_get_VBR_q( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->VBR_q && 10 > gfp->VBR_q ); + + return gfp->VBR_q; +} + + +/* Ignored except for VBR = vbr_abr (ABR mode) */ +int +lame_set_VBR_mean_bitrate_kbps( lame_global_flags* gfp, + int VBR_mean_bitrate_kbps ) +{ + gfp->VBR_mean_bitrate_kbps = VBR_mean_bitrate_kbps; + + return 0; +} + +int +lame_get_VBR_mean_bitrate_kbps( const lame_global_flags* gfp ) +{ + return gfp->VBR_mean_bitrate_kbps; +} + +int +lame_set_VBR_min_bitrate_kbps( lame_global_flags* gfp, + int VBR_min_bitrate_kbps ) +{ + gfp->VBR_min_bitrate_kbps = VBR_min_bitrate_kbps; + + return 0; +} + +int +lame_get_VBR_min_bitrate_kbps( const lame_global_flags* gfp ) +{ + return gfp->VBR_min_bitrate_kbps; +} + +int +lame_set_VBR_max_bitrate_kbps( lame_global_flags* gfp, + int VBR_max_bitrate_kbps ) +{ + gfp->VBR_max_bitrate_kbps = VBR_max_bitrate_kbps; + + return 0; +} + +int +lame_get_VBR_max_bitrate_kbps( const lame_global_flags* gfp ) +{ + return gfp->VBR_max_bitrate_kbps; +} + + +/* + * Strictly enforce VBR_min_bitrate. + * Normally it will be violated for analog silence. + */ +int +lame_set_VBR_hard_min( lame_global_flags* gfp, + int VBR_hard_min ) +{ + /* default = 0 (disabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > VBR_hard_min || 1 < VBR_hard_min ) + return -1; + + gfp->VBR_hard_min = VBR_hard_min; + + return 0; +} + +int +lame_get_VBR_hard_min( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->VBR_hard_min && 1 >= gfp->VBR_hard_min ); + + return gfp->VBR_hard_min; +} + + +/******************************************************************** + * Filtering control + ***********************************************************************/ + +/* + * Freqency in Hz to apply lowpass. + * 0 = default = lame chooses + * -1 = disabled + */ +int +lame_set_lowpassfreq( lame_global_flags* gfp, + int lowpassfreq ) +{ + gfp->lowpassfreq = lowpassfreq; + + return 0; +} + +int +lame_get_lowpassfreq( const lame_global_flags* gfp ) +{ + return gfp->lowpassfreq; +} + + +/* + * Width of transition band (in Hz). + * default = one polyphase filter band + */ +int +lame_set_lowpasswidth( lame_global_flags* gfp, + int lowpasswidth ) +{ + gfp->lowpasswidth = lowpasswidth; + + return 0; +} + +int +lame_get_lowpasswidth( const lame_global_flags* gfp ) +{ + return gfp->lowpasswidth; +} + + +/* + * Frequency in Hz to apply highpass. + * 0 = default = lame chooses + * -1 = disabled + */ +int +lame_set_highpassfreq( lame_global_flags* gfp, + int highpassfreq ) +{ + gfp->highpassfreq = highpassfreq; + + return 0; +} + +int +lame_get_highpassfreq( const lame_global_flags* gfp ) +{ + return gfp->highpassfreq; +} + + +/* + * Width of transition band (in Hz). + * default = one polyphase filter band + */ +int +lame_set_highpasswidth( lame_global_flags* gfp, + int highpasswidth ) +{ + gfp->highpasswidth = highpasswidth; + + return 0; +} + +int +lame_get_highpasswidth( const lame_global_flags* gfp ) +{ + return gfp->highpasswidth; +} + + + + +/* + * psycho acoustics and other arguments which you should not change + * unless you know what you are doing + */ + +/* Only use ATH for masking. */ +int +lame_set_ATHonly( lame_global_flags* gfp, + int ATHonly ) +{ + gfp->ATHonly = ATHonly; + + return 0; +} + +int +lame_get_ATHonly( const lame_global_flags* gfp ) +{ + return gfp->ATHonly; +} + + +/* Only use ATH for short blocks. */ +int +lame_set_ATHshort( lame_global_flags* gfp, + int ATHshort ) +{ + gfp->ATHshort = ATHshort; + + return 0; +} + +int +lame_get_ATHshort( const lame_global_flags* gfp ) +{ + return gfp->ATHshort; +} + + +/* Disable ATH. */ +int +lame_set_noATH( lame_global_flags* gfp, + int noATH ) +{ + gfp->noATH = noATH; + + return 0; +} + +int +lame_get_noATH( const lame_global_flags* gfp ) +{ + return gfp->noATH; +} + + +/* Select ATH formula. */ +int +lame_set_ATHtype( lame_global_flags* gfp, + int ATHtype ) +{ + /* XXX: ATHtype should be converted to an enum. */ + gfp->ATHtype = ATHtype; + + return 0; +} + +int +lame_get_ATHtype( const lame_global_flags* gfp ) +{ + return gfp->ATHtype; +} + + +/* Lower ATH by this many db. */ +int +lame_set_ATHlower( lame_global_flags* gfp, + float ATHlower ) +{ + gfp->ATHlower = ATHlower; + return 0; +} + +float +lame_get_ATHlower( const lame_global_flags* gfp ) +{ + return gfp->ATHlower; +} + + +/* Select ATH adaptive adjustment scheme. */ +int +lame_set_athaa_type( lame_global_flags* gfp, + int athaa_type ) +{ + gfp->athaa_type = athaa_type; + + return 0; +} + +int +lame_get_athaa_type( const lame_global_flags* gfp ) +{ + return gfp->athaa_type; +} + + +/* Select the loudness approximation used by the ATH adaptive auto-leveling. */ +int +lame_set_athaa_loudapprox( lame_global_flags* gfp, + int athaa_loudapprox ) +{ + gfp->athaa_loudapprox = athaa_loudapprox; + + return 0; +} + +int +lame_get_athaa_loudapprox( const lame_global_flags* gfp ) +{ + return gfp->athaa_loudapprox; +} + + +/* Adjust (in dB) the point below which adaptive ATH level adjustment occurs. */ +int +lame_set_athaa_sensitivity( lame_global_flags* gfp, + float athaa_sensitivity ) +{ + gfp->athaa_sensitivity = athaa_sensitivity; + + return 0; +} + +float +lame_get_athaa_sensitivity( const lame_global_flags* gfp ) +{ + return gfp->athaa_sensitivity; +} + + +/* Predictability limit (ISO tonality formula) */ +int +lame_set_cwlimit( lame_global_flags* gfp, + int cwlimit ) +{ + gfp->cwlimit = cwlimit; + + return 0; +} + +int +lame_get_cwlimit( const lame_global_flags* gfp ) +{ + return gfp->cwlimit; +} + + + +/* + * Allow blocktypes to differ between channels. + * default: + * 0 for jstereo => block types coupled + * 1 for stereo => block types may differ + */ +int +lame_set_allow_diff_short( lame_global_flags* gfp, + int allow_diff_short ) +{ + gfp->short_blocks = + allow_diff_short ? short_block_allowed : short_block_coupled; + + return 0; +} + +int +lame_get_allow_diff_short( const lame_global_flags* gfp ) +{ + if ( gfp->short_blocks == short_block_allowed ) + return 1; /* short blocks allowed to differ */ + else + return 0; /* not set, dispensed, forced or coupled */ +} + + +/* Use temporal masking effect */ +int +lame_set_useTemporal( lame_global_flags* gfp, + int useTemporal ) +{ + /* default = 1 (enabled) */ + + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > useTemporal || 1 < useTemporal ) + return -1; + + gfp->useTemporal = useTemporal; + + return 0; +} + +int +lame_get_useTemporal( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->useTemporal && 1 >= gfp->useTemporal ); + + return gfp->useTemporal; +} + + +/* Disable short blocks. */ +int +lame_set_no_short_blocks( lame_global_flags* gfp, + int no_short_blocks ) +{ + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > no_short_blocks || 1 < no_short_blocks ) + return -1; + + gfp->short_blocks = + no_short_blocks ? short_block_dispensed : short_block_allowed; + + return 0; +} +int +lame_get_no_short_blocks( const lame_global_flags* gfp ) +{ + switch ( gfp->short_blocks ) { + default: + case short_block_not_set: return -1; + case short_block_dispensed: return 1; + case short_block_allowed: + case short_block_coupled: + case short_block_forced: return 0; + } +} + + +/* Force short blocks. */ +int +lame_set_force_short_blocks( lame_global_flags* gfp, + int short_blocks ) +{ + /* enforce disable/enable meaning, if we need more than two values + we need to switch to an enum to have an apropriate representation + of the possible meanings of the value */ + if ( 0 > short_blocks || 1 < short_blocks ) + return -1; + + if (short_blocks == 1) + gfp->short_blocks = short_block_forced; + else if (gfp->short_blocks == short_block_forced) + gfp->short_blocks = short_block_allowed; + + return 0; +} +int +lame_get_force_short_blocks( const lame_global_flags* gfp ) +{ + switch ( gfp->short_blocks ) { + default: + case short_block_not_set: return -1; + case short_block_dispensed: + case short_block_allowed: + case short_block_coupled: return 0; + case short_block_forced: return 1; + } +} + + +/* + * Input PCM is emphased PCM + * (for instance from one of the rarely emphased CDs). + * + * It is STRONGLY not recommended to use this, because psycho does not + * take it into account, and last but not least many decoders + * ignore these bits + */ +int +lame_set_emphasis( lame_global_flags* gfp, + int emphasis ) +{ + /* XXX: emphasis should be converted to an enum */ + if ( 0 > emphasis || 4 <= emphasis ) + return -1; + + gfp->emphasis = emphasis; + + return 0; +} + +int +lame_get_emphasis( const lame_global_flags* gfp ) +{ + assert( 0 <= gfp->emphasis && 4 > gfp->emphasis ); + + return gfp->emphasis; +} + + + + +/***************************************************************/ +/* internal variables, cannot be set... */ +/* provided because they may be of use to calling application */ +/***************************************************************/ + +/* MPEG version. + * 0 = MPEG-2 + * 1 = MPEG-1 + * (2 = MPEG-2.5) + */ +int +lame_get_version( const lame_global_flags* gfp ) +{ + return gfp->version; +} + + +/* Encoder delay. */ +int +lame_get_encoder_delay( const lame_global_flags* gfp ) +{ + return gfp->encoder_delay; +} + +/* padding added to the end of the input */ +int +lame_get_encoder_padding( const lame_global_flags* gfp ) +{ + return gfp->encoder_padding; +} + + +/* Size of MPEG frame. */ +int +lame_get_framesize( const lame_global_flags* gfp ) +{ + return gfp->framesize; +} + + +/* Number of frames encoded so far. */ +int +lame_get_frameNum( const lame_global_flags* gfp ) +{ + return gfp->frameNum; +} + +int +lame_get_mf_samples_to_encode( const lame_global_flags* gfp ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + return gfc->mf_samples_to_encode; +} + + +int CDECL lame_get_size_mp3buffer( const lame_global_flags* gfp ) +{ + int size; + compute_flushbits(gfp,&size); + return size; +} + + + +/* + * LAME's estimate of the total number of frames to be encoded. + * Only valid if calling program set num_samples. + */ +int +lame_get_totalframes( const lame_global_flags* gfp ) +{ + int totalframes; + /* estimate based on user set num_samples: */ + totalframes = + 2 + ((double)gfp->num_samples * gfp->out_samplerate) / + ((double)gfp->in_samplerate * gfp->framesize); + + /* check to see if we underestimated totalframes */ + // if (totalframes < gfp->frameNum) + // totalframes = gfp->frameNum; + + return totalframes; +} + + +/* + +UNDOCUMENTED, experimental settings. These routines are not prototyped +in lame.h. You should not use them, they are experimental and may +change. + +*/ + + +/* + * just another daily changing developer switch + */ +void lame_set_tune( lame_global_flags* gfp, float val ) +{ + gfp->tune_value_a = val; + gfp->tune = 1; +} + +/* Custom msfix hack */ +void +lame_set_msfix( lame_global_flags* gfp, double msfix ) +{ + /* default = 0 */ + gfp->msfix = msfix; + +} + +int +lame_set_preset_expopts( lame_global_flags* gfp, int preset_expopts ) +{ + + lame_internal_flags *gfc = gfp->internal_flags; + + gfc->presetTune.use = 1; + + /* default = 0 (disabled) */ + gfp->preset_expopts = preset_expopts; + + switch (preset_expopts) + { + case 1: + + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 1); + lame_set_experimentalX(gfp, 3); + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2); // safejoint + lame_set_ATHtype(gfp, 2); + + gfc->presetTune.attackthre = 35; + gfc->presetTune.attackthre_s = 150; + gfc->presetTune.ms_maskadjust = .5; + gfc->presetTune.quantcomp_type_s = 3; + gfc->presetTune.quantcomp_alt_type = 3; + gfc->presetTune.athadjust_switch_level = 2; // Always switch + + break; + + case 2: + + if (gfp->VBR == vbr_mtrh) { + lame_set_experimentalX(gfp, 2); + gfc->presetTune.quantcomp_adjust_mtrh = 9; + gfc->presetTune.quantcomp_type_s = 4; + gfc->presetTune.quantcomp_alt_type = 0; + gfc->presetTune.athadjust_safe_noiseshaping_thre = 0.0; + gfc->presetTune.athadjust_safe_athaasensitivity = 8.0; + } + else { + lame_set_experimentalX(gfp, 3); + gfc->presetTune.quantcomp_adjust_rh_tot = 600; + gfc->presetTune.quantcomp_adjust_rh_max = 60; + gfc->presetTune.quantcomp_type_s = 3; + gfc->presetTune.quantcomp_alt_type = 1; + } + + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 1); + lame_set_experimentalZ(gfp, 1); + lame_set_VBR_q(gfp, 2); + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2); // safejoint + lame_set_ATHtype(gfp, 2); + // modify sfb21 by 3 dB plus ns-treble=0 + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (12 << 20)); + + gfc->presetTune.attackthre = 35; + gfc->presetTune.attackthre_s = 150; + gfc->presetTune.ms_maskadjust = .5; + gfc->presetTune.athadjust_switch_level = 1; + gfc->presetTune.athadjust_msfix = 2.13; + + break; + + case 3: + + if (gfp->VBR == vbr_mtrh) { + gfc->presetTune.quantcomp_type_s = 4; + gfc->presetTune.quantcomp_adjust_mtrh = 9; + gfc->presetTune.quantcomp_alt_type = 0; + (void) lame_set_ATHlower( gfp, -2 ); + gfc->presetTune.athadjust_safe_noiseshaping_thre = 0.0; + gfc->presetTune.athadjust_safe_athaasensitivity = 8.0; + } + else { + gfc->presetTune.quantcomp_type_s = 3; + gfc->presetTune.quantcomp_adjust_rh_tot = 600; + gfc->presetTune.quantcomp_adjust_rh_max = 60; + (void) lame_set_ATHlower( gfp, -1 ); + } + + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 1); + lame_set_experimentalZ(gfp, 1); + lame_set_experimentalX(gfp, 1); + lame_set_VBR_q(gfp, 2); + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | 2); // safejoint + (void) lame_set_msfix( gfp, 2.13 ); + lame_set_ATHtype(gfp, 4); + // modify sfb21 by 3.75 dB plus ns-treble=0 + lame_set_exp_nspsytune(gfp, lame_get_exp_nspsytune(gfp) | (15 << 20)); + + gfc->presetTune.attackthre = 35; + gfc->presetTune.attackthre_s = 150; + gfc->presetTune.ms_maskadjust = .5; + gfc->presetTune.athadjust_switch_level = 1; + + break; + } + return 0; +} + +int +lame_set_preset_notune( lame_global_flags* gfp, int preset_notune ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + + gfc->presetTune.use = 0; // Turn off specialized preset tunings + + return 0; +} + + + + + + + + + + + + + + + + + + + diff --git a/lib/lame/tables.c b/lib/lame/tables.c new file mode 100644 index 0000000..bb27a68 --- /dev/null +++ b/lib/lame/tables.c @@ -0,0 +1,507 @@ +/* + * MPEG layer 3 tables source file + * + * Copyright (c) 1999 Albert L Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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: tables.c,v 1.1 2002/04/28 17:30:29 kramm Exp $ */ + +#include "config_static.h" + +#include "util.h" +#include "tables.h" + +#ifdef WITH_DMALLOC +#include +#endif + +static const short t1HB[] = { + 1, 1, + 1, 0}; + +static const short t2HB[] = { + 1, 2, 1, + 3, 1, 1, + 3, 2, 0}; + +static const short t3HB[] = { + 3, 2, 1, + 1, 1, 1, + 3, 2, 0}; + +static const short t5HB[] = { + 1, 2, 6, 5, + 3, 1, 4, 4, + 7, 5, 7, 1, + 6, 1, 1, 0}; + +static const short t6HB[] = { + 7, 3, 5, 1, + 6, 2, 3, 2, + 5, 4, 4, 1, + 3, 3, 2, 0}; + +static const short t7HB[] = { + 1, 2,10,19,16,10, + 3, 3, 7,10, 5, 3, + 11, 4,13,17, 8, 4, + 12,11,18,15,11, 2, + 7, 6, 9,14, 3, 1, + 6, 4, 5, 3, 2, 0}; + +static const short t8HB[] = { + 3, 4, 6, 18,12, 5, + 5, 1, 2, 16, 9, 3, + 7, 3, 5, 14, 7, 3, + 19,17,15, 13,10, 4, + 13, 5, 8, 11, 5, 1, + 12, 4, 4, 1, 1, 0}; + +static const short t9HB[] = { + 7, 5, 9, 14, 15, 7, + 6, 4, 5, 5, 6, 7, + 7, 6, 8, 8, 8, 5, + 15, 6, 9, 10, 5, 1, + 11, 7, 9, 6, 4, 1, + 14, 4, 6, 2, 6, 0}; + +static const short t10HB[] = { + 1, 2, 10, 23, 35, 30, 12, 17, + 3, 3, 8, 12, 18, 21, 12, 7, + 11, 9, 15, 21, 32, 40, 19, 6, + 14,13, 22, 34, 46, 23, 18, 7, + 20,19, 33, 47, 27, 22, 9, 3, + 31,22, 41, 26, 21, 20, 5, 3, + 14,13, 10, 11, 16, 6, 5, 1, + 9, 8, 7, 8, 4, 4, 2, 0}; + +static const short t11HB[] = { + 3, 4, 10, 24, 34, 33, 21, 15, + 5, 3, 4, 10, 32, 17, 11, 10, + 11, 7, 13, 18, 30, 31, 20, 5, + 25,11, 19, 59, 27, 18, 12, 5, + 35,33, 31, 58, 30, 16, 7, 5, + 28,26, 32, 19, 17, 15, 8, 14, + 14,12, 9, 13, 14, 9, 4, 1, + 11, 4, 6, 6, 6, 3, 2, 0}; + +static const short t12HB[] = { + 9, 6, 16, 33, 41, 39, 38,26, + 7, 5, 6, 9, 23, 16, 26,11, + 17, 7, 11, 14, 21, 30, 10, 7, + 17, 10, 15, 12, 18, 28, 14, 5, + 32, 13, 22, 19, 18, 16, 9, 5, + 40, 17, 31, 29, 17, 13, 4, 2, + 27, 12, 11, 15, 10, 7, 4, 1, + 27, 12, 8, 12, 6, 3, 1, 0}; + +static const short t13HB[] = { + 1, 5, 14, 21, 34, 51, 46, 71, 42, 52, 68, 52, 67, 44, 43, 19, + 3, 4, 12, 19, 31, 26, 44, 33, 31, 24, 32, 24, 31, 35, 22, 14, + 15, 13, 23, 36, 59, 49, 77, 65, 29, 40, 30, 40, 27, 33, 42, 16, + 22, 20, 37, 61, 56, 79, 73, 64, 43, 76, 56, 37, 26, 31, 25, 14, + 35, 16, 60, 57, 97, 75,114, 91, 54, 73, 55, 41, 48, 53, 23, 24, + 58, 27, 50, 96, 76, 70, 93, 84, 77, 58, 79, 29, 74, 49, 41, 17, + 47, 45, 78, 74,115, 94, 90, 79, 69, 83, 71, 50, 59, 38, 36, 15, + 72, 34, 56, 95, 92, 85, 91, 90, 86, 73, 77, 65, 51, 44, 43, 42, + 43, 20, 30, 44, 55, 78, 72, 87, 78, 61, 46, 54, 37, 30, 20, 16, + 53, 25, 41, 37, 44, 59, 54, 81, 66, 76, 57, 54, 37, 18, 39, 11, + 35, 33, 31, 57, 42, 82, 72, 80, 47, 58, 55, 21, 22, 26, 38, 22, + 53, 25, 23, 38, 70, 60, 51, 36, 55, 26, 34, 23, 27, 14, 9, 7, + 34, 32, 28, 39, 49, 75, 30, 52, 48, 40, 52, 28, 18, 17, 9, 5, + 45, 21, 34, 64, 56, 50, 49, 45, 31, 19, 12, 15, 10, 7, 6, 3, + 48, 23, 20, 39, 36, 35, 53, 21, 16, 23, 13, 10, 6, 1, 4, 2, + 16, 15, 17, 27, 25, 20, 29, 11, 17, 12, 16, 8, 1, 1, 0, 1}; + +static const short t15HB[] = { + 7, 12, 18, 53, 47, 76,124,108, 89,123,108,119,107, 81,122, 63, + 13, 5, 16, 27, 46, 36, 61, 51, 42, 70, 52, 83, 65, 41, 59, 36, + 19, 17, 15, 24, 41, 34, 59, 48, 40, 64, 50, 78, 62, 80, 56, 33, + 29, 28, 25, 43, 39, 63, 55, 93, 76, 59, 93, 72, 54, 75, 50, 29, + 52, 22, 42, 40, 67, 57, 95, 79, 72, 57, 89, 69, 49, 66, 46, 27, + 77, 37, 35, 66, 58, 52, 91, 74, 62, 48, 79, 63, 90, 62, 40, 38, + 125, 32, 60, 56, 50, 92, 78, 65, 55, 87, 71, 51, 73, 51, 70, 30, + 109, 53, 49, 94, 88, 75, 66,122, 91, 73, 56, 42, 64, 44, 21, 25, + 90, 43, 41, 77, 73, 63, 56, 92, 77, 66, 47, 67, 48, 53, 36, 20, + 71, 34, 67, 60, 58, 49, 88, 76, 67,106, 71, 54, 38, 39, 23, 15, + 109, 53, 51, 47, 90, 82, 58, 57, 48, 72, 57, 41, 23, 27, 62, 9, + 86, 42, 40, 37, 70, 64, 52, 43, 70, 55, 42, 25, 29, 18, 11, 11, + 118, 68, 30, 55, 50, 46, 74, 65, 49, 39, 24, 16, 22, 13, 14, 7, + 91, 44, 39, 38, 34, 63, 52, 45, 31, 52, 28, 19, 14, 8, 9, 3, + 123, 60, 58, 53, 47, 43, 32, 22, 37, 24, 17, 12, 15, 10, 2, 1, + 71, 37, 34, 30, 28, 20, 17, 26, 21, 16, 10, 6, 8, 6, 2, 0}; + +static const short t16HB[] = { + 1, 5, 14, 44, 74, 63, 110, 93, 172, 149, 138, 242, 225, 195, 376, 17, + 3, 4, 12, 20, 35, 62, 53, 47, 83, 75, 68, 119, 201, 107, 207, 9, + 15, 13, 23, 38, 67, 58, 103, 90, 161, 72, 127, 117, 110, 209, 206, 16, + 45, 21, 39, 69, 64,114, 99, 87, 158, 140, 252, 212, 199, 387, 365, 26, + 75, 36, 68, 65,115,101, 179,164, 155, 264, 246, 226, 395, 382, 362, 9, + 66, 30, 59, 56,102,185, 173,265, 142, 253, 232, 400, 388, 378, 445, 16, + 111, 54, 52,100,184,178, 160,133, 257, 244, 228, 217, 385, 366, 715, 10, + 98, 48, 91, 88,165,157, 148,261, 248, 407, 397, 372, 380, 889, 884, 8, + 85, 84, 81,159,156,143, 260,249, 427, 401, 392, 383, 727, 713, 708, 7, + 154, 76, 73,141,131,256, 245,426, 406, 394, 384, 735, 359, 710, 352, 11, + 139, 129, 67,125,247,233, 229,219, 393, 743, 737, 720, 885, 882, 439, 4, + 243, 120,118,115,227,223, 396,746, 742, 736, 721, 712, 706, 223, 436, 6, + 202, 224,222,218,216,389, 386,381, 364, 888, 443, 707, 440, 437,1728, 4, + 747, 211,210,208,370,379, 734,723, 714,1735, 883, 877, 876,3459, 865, 2, + 377, 369,102,187,726,722, 358,711, 709, 866,1734, 871,3458, 870, 434, 0, + 12, 10, 7, 11, 10, 17, 11, 9, 13, 12, 10, 7, 5, 3, 1, 3}; + +static const short t24HB[] = { + 15, 13, 46, 80, 146, 262, 248, 434, 426, 669, 653, 649, 621, 517, 1032, 88, + 14, 12, 21, 38, 71, 130, 122, 216, 209, 198, 327, 345, 319, 297, 279, 42, + 47, 22, 41, 74, 68, 128, 120, 221, 207, 194, 182, 340, 315, 295, 541, 18, + 81, 39, 75, 70, 134, 125, 116, 220, 204, 190, 178, 325, 311, 293, 271, 16, + 147, 72, 69,135, 127, 118, 112, 210, 200, 188, 352, 323, 306, 285, 540, 14, + 263, 66,129,126, 119, 114, 214, 202, 192, 180, 341, 317, 301, 281, 262, 12, + 249,123,121,117, 113, 215, 206, 195, 185, 347, 330, 308, 291, 272, 520, 10, + 435,115,111,109, 211, 203, 196, 187, 353, 332, 313, 298, 283, 531, 381, 17, + 427,212,208,205, 201, 193, 186, 177, 169, 320, 303, 286, 268, 514, 377, 16, + 335,199,197,191, 189, 181, 174, 333, 321, 305, 289, 275, 521, 379, 371, 11, + 668,184,183,179, 175, 344, 331, 314, 304, 290, 277, 530, 383, 373, 366, 10, + 652,346,171,168, 164, 318, 309, 299, 287, 276, 263, 513, 375, 368, 362, 6, + 648,322,316,312, 307, 302, 292, 284, 269, 261, 512, 376, 370, 364, 359, 4, + 620,300,296,294, 288, 282, 273, 266, 515, 380, 374, 369, 365, 361, 357, 2, + 1033,280,278,274, 267, 264, 259, 382, 378, 372, 367, 363, 360, 358, 356, 0, + 43, 20, 19, 17, 15, 13, 11, 9, 7, 6, 4, 7, 5, 3, 1, 3}; + +static const short t32HB[] = { + 1 << 0, 5 << 1, 4 << 1, 5 << 2, 6 << 1, 5 << 2, 4 << 2, 4 << 3, + 7 << 1, 3 << 2, 6 << 2, 0 << 3, 7 << 2, 2 << 3, 3 << 3, 1 << 4}; + +static const short t33HB[] = { + 15 << 0, 14 << 1, 13 << 1, 12 << 2, 11 << 1, 10 << 2, 9 << 2, 8 << 3, + 7 << 1, 6 << 2, 5 << 2, 4 << 3, 3 << 2, 2 << 3, 1 << 3, 0 << 4}; + + +const char t1l[] = { + 1, 4, + 3, 5}; + +const char t2l[] = { + 1, 4, 7, + 4, 5, 7, + 6, 7, 8}; + +const char t3l[] = { + 2, 3, 7, + 4, 4, 7, + 6, 7, 8}; + +const char t5l[] = { + 1, 4, 7, 8, + 4, 5, 8, 9, + 7, 8, 9, 10, + 8, 8, 9, 10}; + +const char t6l[] = { + 3, 4, 6, 8, + 4, 4, 6, 7, + 5, 6, 7, 8, + 7, 7, 8, 9}; + +const char t7l[] = { + 1, 4, 7, 9, 9, 10, + 4, 6, 8, 9, 9, 10, + 7, 7, 9, 10, 10, 11, + 8, 9, 10, 11, 11, 11, + 8, 9, 10, 11, 11, 12, + 9, 10, 11, 12, 12, 12}; + +const char t8l[] = { + 2, 4, 7, 9, 9, 10, + 4, 4, 6, 10, 10, 10, + 7, 6, 8, 10, 10, 11, + 9, 10, 10, 11, 11, 12, + 9, 9, 10, 11, 12, 12, +10, 10, 11, 11, 13, 13}; + +const char t9l[] = { + 3, 4, 6, 7, 9, 10, + 4, 5, 6, 7, 8, 10, + 5, 6, 7, 8, 9, 10, + 7, 7, 8, 9, 9, 10, + 8, 8, 9, 9, 10, 11, + 9, 9, 10, 10, 11, 11}; + +const char t10l[] = { + 1, 4, 7, 9, 10, 10, 10, 11, + 4, 6, 8, 9, 10, 11, 10, 10, + 7, 8, 9, 10, 11, 12, 11, 11, + 8, 9, 10, 11, 12, 12, 11, 12, + 9, 10, 11, 12, 12, 12, 12, 12, +10, 11, 12, 12, 13, 13, 12, 13, + 9, 10, 11, 12, 12, 12, 13, 13, +10, 10, 11, 12, 12, 13, 13, 13}; + +const char t11l[] = { + 2, 4, 6, 8, 9, 10, 9, 10, + 4, 5, 6, 8, 10, 10, 9, 10, + 6, 7, 8, 9, 10, 11, 10, 10, + 8, 8, 9, 11, 10, 12, 10, 11, + 9, 10, 10, 11, 11, 12, 11, 12, + 9, 10, 11, 12, 12, 13, 12, 13, + 9, 9, 9, 10, 11, 12, 12, 12, + 9, 9, 10, 11, 12, 12, 12, 12}; + +const char t12l[] = { + 4, 4, 6, 8, 9, 10, 10, 10, + 4, 5, 6, 7, 9, 9, 10, 10, + 6, 6, 7, 8, 9, 10, 9, 10, + 7, 7, 8, 8, 9, 10, 10, 10, + 8, 8, 9, 9, 10, 10, 10, 11, + 9, 9, 10, 10, 10, 11, 10, 11, + 9, 9, 9, 10, 10, 11, 11, 12, +10, 10, 10, 11, 11, 11, 11, 12}; + +const char t13l[] = { + 1, 5, 7, 8, 9, 10, 10, 11, 10, 11, 12, 12, 13, 13, 14, 14, + 4, 6, 8, 9, 10, 10, 11, 11, 11, 11, 12, 12, 13, 14, 14, 14, + 7, 8, 9, 10, 11, 11, 12, 12, 11, 12, 12, 13, 13, 14, 15, 15, + 8, 9, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 15, 15, + 9, 9, 11, 11, 12, 12, 13, 13, 12, 13, 13, 14, 14, 15, 15, 16, +10, 10, 11, 12, 12, 12, 13, 13, 13, 13, 14, 13, 15, 15, 16, 16, +10, 11, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14, 15, 15, 16, 16, +11, 11, 12, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 16, 18, 18, +10, 10, 11, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 16, 17, 17, +11, 11, 12, 12, 13, 13, 13, 15, 14, 15, 15, 16, 16, 16, 18, 17, +11, 12, 12, 13, 13, 14, 14, 15, 14, 15, 16, 15, 16, 17, 18, 19, +12, 12, 12, 13, 14, 14, 14, 14, 15, 15, 15, 16, 17, 17, 17, 18, +12, 13, 13, 14, 14, 15, 14, 15, 16, 16, 17, 17, 17, 18, 18, 18, +13, 13, 14, 15, 15, 15, 16, 16, 16, 16, 16, 17, 18, 17, 18, 18, +14, 14, 14, 15, 15, 15, 17, 16, 16, 19, 17, 17, 17, 19, 18, 18, +13, 14, 15, 16, 16, 16, 17, 16, 17, 17, 18, 18, 21, 20, 21, 18}; + +const char t15l[] = { + 3, 5, 6, 8, 8, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 14, + 5, 5, 7, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, + 6, 7, 7, 8, 9, 9, 10, 10, 10, 11, 11, 12, 12, 13, 13, 13, + 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, + 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 13, + 9, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 13, 13, 13, 14, +10, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, +10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 14, +10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 14, 14, 14, +10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, +11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 15, 14, +11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, +12, 12, 11, 12, 12, 12, 13, 13, 13, 13, 13, 13, 14, 14, 15, 15, +12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 14, 15, +13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15}; + +const char t16_5l[] = { + 1, 5, 7, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 11, + 4, 6, 8, 9, 10, 11, 11, 11, 12, 12, 12, 13, 14, 13, 14, 11, + 7, 8, 9, 10, 11, 11, 12, 12, 13, 12, 13, 13, 13, 14, 14, 12, + 9, 9, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 13, +10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 12, +10, 10, 11, 11, 12, 13, 13, 14, 13, 14, 14, 15, 15, 15, 16, 13, +11, 11, 11, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 16, 13, +11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 17, 17, 13, +11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 13, +12, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 15, 16, 15, 14, +12, 13, 12, 13, 14, 14, 14, 14, 15, 16, 16, 16, 17, 17, 16, 13, +13, 13, 13, 13, 14, 14, 15, 16, 16, 16, 16, 16, 16, 15, 16, 14, +13, 14, 14, 14, 14, 15, 15, 15, 15, 17, 16, 16, 16, 16, 18, 14, +15, 14, 14, 14, 15, 15, 16, 16, 16, 18, 17, 17, 17, 19, 17, 14, +14, 15, 13, 14, 16, 16, 15, 16, 16, 17, 18, 17, 19, 17, 16, 14, +11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 12}; + +const char t16l[] = { + 1, 5, 7, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 14, 10, + 4, 6, 8, 9, 10, 11, 11, 11, 12, 12, 12, 13, 14, 13, 14, 10, + 7, 8, 9, 10, 11, 11, 12, 12, 13, 12, 13, 13, 13, 14, 14, 11, + 9, 9, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 12, +10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 11, +10, 10, 11, 11, 12, 13, 13, 14, 13, 14, 14, 15, 15, 15, 16, 12, +11, 11, 11, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 16, 12, +11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 17, 17, 12, +11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 12, +12, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 15, 16, 15, 13, +12, 13, 12, 13, 14, 14, 14, 14, 15, 16, 16, 16, 17, 17, 16, 12, +13, 13, 13, 13, 14, 14, 15, 16, 16, 16, 16, 16, 16, 15, 16, 13, +13, 14, 14, 14, 14, 15, 15, 15, 15, 17, 16, 16, 16, 16, 18, 13, +15, 14, 14, 14, 15, 15, 16, 16, 16, 18, 17, 17, 17, 19, 17, 13, +14, 15, 13, 14, 16, 16, 15, 16, 16, 17, 18, 17, 19, 17, 16, 13, +10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 10}; + +const char t24l[] = { + 4, 5, 7, 8, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 13, 10, + 5, 6, 7, 8, 9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 12, 10, + 7, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 9, + 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 9, + 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 9, +10, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 9, +10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 9, +11, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 10, +11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 10, +11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 10, +12, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 10, +12, 12, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 10, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 10, +12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 10, +13, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 10, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 6}; + +const char t32l[] = { + 1+0, 4+1, 4+1, 5+2, 4+1, 6+2, 5+2, 6+3, + 4+1, 5+2, 5+2, 6+3, 5+2, 6+3, 6+3, 6+4}; + +const char t33l[] = { + 4+0, 4+1, 4+1, 4+2, 4+1, 4+2, 4+2, 4+3, + 4+1, 4+2, 4+2, 4+3, 4+2, 4+3, 4+3, 4+4}; + + +const struct huffcodetab ht[HTN] = +{ + /* xlen, linmax, table, hlen */ + { 0, 0,NULL,NULL}, + { 2, 0,t1HB, t1l}, + { 3, 0,t2HB, t2l}, + { 3, 0,t3HB, t3l}, + { 0, 0,NULL,NULL},/* Apparently not used */ + { 4, 0,t5HB, t5l}, + { 4, 0,t6HB, t6l}, + { 6, 0,t7HB, t7l}, + { 6, 0,t8HB, t8l}, + { 6, 0,t9HB, t9l}, + { 8, 0,t10HB, t10l}, + { 8, 0,t11HB, t11l}, + { 8, 0,t12HB, t12l}, + {16, 0,t13HB, t13l}, + { 0, 0,NULL, t16_5l},/* Apparently not used */ + {16, 0,t15HB, t15l}, + + { 1, 1,t16HB, t16l}, + { 2, 3,t16HB, t16l}, + { 3, 7,t16HB, t16l}, + { 4, 15,t16HB, t16l}, + { 6, 63,t16HB, t16l}, + { 8, 255,t16HB, t16l}, + {10,1023,t16HB, t16l}, + {13,8191,t16HB, t16l}, + + { 4, 15,t24HB, t24l}, + { 5, 31,t24HB, t24l}, + { 6, 63,t24HB, t24l}, + { 7, 127,t24HB, t24l}, + { 8, 255,t24HB, t24l}, + { 9, 511,t24HB, t24l}, + {11,2047,t24HB, t24l}, + {13,8191,t24HB, t24l}, + + { 0, 0,t32HB, t32l}, + { 0, 0,t33HB, t33l}, +}; + + + + + +/* for (i = 0; i < 16*16; i++) { + * largetbl[i] = ((ht[16].hlen[i]) << 16) + ht[24].hlen[i]; + * } + */ +const unsigned int largetbl[16*16] = { +0x010004, 0x050005, 0x070007, 0x090008, 0x0a0009, 0x0a000a, 0x0b000a, 0x0b000b, +0x0c000b, 0x0c000c, 0x0c000c, 0x0d000c, 0x0d000c, 0x0d000c, 0x0e000d, 0x0a000a, +0x040005, 0x060006, 0x080007, 0x090008, 0x0a0009, 0x0b000a, 0x0b000a, 0x0b000b, +0x0c000b, 0x0c000b, 0x0c000c, 0x0d000c, 0x0e000c, 0x0d000c, 0x0e000c, 0x0a000a, +0x070007, 0x080007, 0x090008, 0x0a0009, 0x0b0009, 0x0b000a, 0x0c000a, 0x0c000b, +0x0d000b, 0x0c000b, 0x0d000b, 0x0d000c, 0x0d000c, 0x0e000c, 0x0e000d, 0x0b0009, +0x090008, 0x090008, 0x0a0009, 0x0b0009, 0x0b000a, 0x0c000a, 0x0c000a, 0x0c000b, +0x0d000b, 0x0d000b, 0x0e000b, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x0c0009, +0x0a0009, 0x0a0009, 0x0b0009, 0x0b000a, 0x0c000a, 0x0c000a, 0x0d000a, 0x0d000b, +0x0d000b, 0x0e000b, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000d, 0x0b0009, +0x0a000a, 0x0a0009, 0x0b000a, 0x0b000a, 0x0c000a, 0x0d000a, 0x0d000b, 0x0e000b, +0x0d000b, 0x0e000b, 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000c, 0x10000c, 0x0c0009, +0x0b000a, 0x0b000a, 0x0b000a, 0x0c000a, 0x0d000a, 0x0d000b, 0x0d000b, 0x0d000b, +0x0e000b, 0x0e000c, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x10000d, 0x0c0009, +0x0b000b, 0x0b000a, 0x0c000a, 0x0c000a, 0x0d000b, 0x0d000b, 0x0d000b, 0x0e000b, +0x0e000c, 0x0f000c, 0x0f000c, 0x0f000c, 0x0f000c, 0x11000d, 0x11000d, 0x0c000a, +0x0b000b, 0x0c000b, 0x0c000b, 0x0d000b, 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000b, +0x0f000b, 0x0f000c, 0x0f000c, 0x0f000c, 0x10000c, 0x10000d, 0x10000d, 0x0c000a, +0x0c000b, 0x0c000b, 0x0c000b, 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000b, 0x0f000c, +0x0f000c, 0x0f000c, 0x0f000c, 0x10000c, 0x0f000d, 0x10000d, 0x0f000d, 0x0d000a, +0x0c000c, 0x0d000b, 0x0c000b, 0x0d000b, 0x0e000b, 0x0e000c, 0x0e000c, 0x0e000c, +0x0f000c, 0x10000c, 0x10000c, 0x10000d, 0x11000d, 0x11000d, 0x10000d, 0x0c000a, +0x0d000c, 0x0d000c, 0x0d000b, 0x0d000b, 0x0e000b, 0x0e000c, 0x0f000c, 0x10000c, +0x10000c, 0x10000c, 0x10000c, 0x10000d, 0x10000d, 0x0f000d, 0x10000d, 0x0d000a, +0x0d000c, 0x0e000c, 0x0e000c, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x0f000c, +0x0f000c, 0x11000c, 0x10000d, 0x10000d, 0x10000d, 0x10000d, 0x12000d, 0x0d000a, +0x0f000c, 0x0e000c, 0x0e000c, 0x0e000c, 0x0f000c, 0x0f000c, 0x10000c, 0x10000c, +0x10000d, 0x12000d, 0x11000d, 0x11000d, 0x11000d, 0x13000d, 0x11000d, 0x0d000a, +0x0e000d, 0x0f000c, 0x0d000c, 0x0e000c, 0x10000c, 0x10000c, 0x0f000c, 0x10000d, +0x10000d, 0x11000d, 0x12000d, 0x11000d, 0x13000d, 0x11000d, 0x10000d, 0x0d000a, +0x0a0009, 0x0a0009, 0x0a0009, 0x0b0009, 0x0b0009, 0x0c0009, 0x0c0009, 0x0c0009, +0x0d0009, 0x0d0009, 0x0d0009, 0x0d000a, 0x0d000a, 0x0d000a, 0x0d000a, 0x0a0006 +}; + +/* for (i = 0; i < 3*3; i++) { + * table23[i] = ((ht[2].hlen[i]) << 16) + ht[3].hlen[i]; + * } + */ +const unsigned int table23[3*3] = { +0x010002, 0x040003, 0x070007, +0x040004, 0x050004, 0x070007, +0x060006, 0x070007, 0x080008 +}; + +/* for (i = 0; i < 4*4; i++) { + * table56[i] = ((ht[5].hlen[i]) << 16) + ht[6].hlen[i]; + * } + */ +const unsigned int table56[4*4] = { +0x010003, 0x040004, 0x070006, 0x080008, 0x040004, 0x050004, 0x080006, 0x090007, +0x070005, 0x080006, 0x090007, 0x0a0008, 0x080007, 0x080007, 0x090008, 0x0a0009 +}; + + + +/* + * 0: MPEG-2 LSF + * 1: MPEG-1 + * 2: MPEG-2.5 LSF FhG extention (1995-07-11 shn) + */ + +typedef enum { + MPEG_2 = 0, + MPEG_1 = 1, + MPEG_25 = 2 +} MPEG_t; + +const int bitrate_table [3] [16] = { + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, + { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1 }, + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1 }, +}; + +const int samplerate_table [3] [4] = { + { 22050, 24000, 16000, -1 }, /* MPEG 2 */ + { 44100, 48000, 32000, -1 }, /* MPEG 1 */ + { 11025, 12000, 8000, -1 }, /* MPEG 2.5 */ +}; + +const char* version_string [3] = { "2", "1", "2.5" }; + +const unsigned header_word [3] = { 0xFFF00000, 0xFFF80000, 0xFFE00000 }; + +/* end of tables.h */ diff --git a/lib/lame/tables.h b/lib/lame/tables.h new file mode 100644 index 0000000..486f2b1 --- /dev/null +++ b/lib/lame/tables.h @@ -0,0 +1,90 @@ +/* + * MPEG layer 3 tables include file + * + * Copyright (c) 1999 Albert L Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_TABLES_H +#define LAME_TABLES_H + +#include "machine.h" + +typedef struct { + unsigned char no; + unsigned char width; + unsigned char minval_2; + float quiet_thr; + float norm; + float bark; +} type1_t; + +typedef struct { + unsigned char no; + unsigned char width; + float quiet_thr; + float norm; + float SNR; + float bark; +} type2_t; + +typedef struct { + unsigned int no : 5; + unsigned int cbw : 3; + unsigned int bu : 6; + unsigned int bo : 6; + unsigned int w1_576 : 10; + unsigned int w2_576 : 10; +} type34_t; + +typedef struct { + size_t len1; + const type1_t* const tab1; + size_t len2; + const type2_t* const tab2; + size_t len3; + const type34_t* const tab3; + size_t len4; + const type34_t* const tab4; +} type5_t; + +extern const type5_t table5 [6]; + + + +#define HTN 34 + +struct huffcodetab { + const int xlen; /* max. x-index+ */ + const int linmax; /* max number to be stored in linbits */ + const short* table; /* pointer to array[xlen][ylen] */ + const char* hlen; /* pointer to array[xlen][ylen] */ +}; + +extern const struct huffcodetab ht [HTN]; + /* global memory block */ + /* array of all huffcodtable headers */ + /* 0..31 Huffman code table 0..31 */ + /* 32,33 count1-tables */ + +extern const char t32l []; +extern const char t33l []; + +extern const unsigned int largetbl [16*16]; +extern const unsigned int table23 [3*3]; +extern const unsigned int table56 [4*4]; +#endif /* LAME_TABLES_H */ diff --git a/lib/lame/takehiro.c b/lib/lame/takehiro.c new file mode 100644 index 0000000..13507ba --- /dev/null +++ b/lib/lame/takehiro.c @@ -0,0 +1,1030 @@ +/* + * MP3 huffman table selecting and bit counting + * + * Copyright (c) 1999 Takehiro TOMINAGA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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: takehiro.c,v 1.1 2002/04/28 17:30:29 kramm Exp $ */ + +#include "config_static.h" + +#include +#include "util.h" +#include "l3side.h" +#include "tables.h" +#include "quantize_pvt.h" + +#ifdef WITH_DMALLOC +#include +#endif + +static const struct +{ + const int region0_count; + const int region1_count; +} subdv_table[ 23 ] = +{ +{0, 0}, /* 0 bands */ +{0, 0}, /* 1 bands */ +{0, 0}, /* 2 bands */ +{0, 0}, /* 3 bands */ +{0, 0}, /* 4 bands */ +{0, 1}, /* 5 bands */ +{1, 1}, /* 6 bands */ +{1, 1}, /* 7 bands */ +{1, 2}, /* 8 bands */ +{2, 2}, /* 9 bands */ +{2, 3}, /* 10 bands */ +{2, 3}, /* 11 bands */ +{3, 4}, /* 12 bands */ +{3, 4}, /* 13 bands */ +{3, 4}, /* 14 bands */ +{4, 5}, /* 15 bands */ +{4, 5}, /* 16 bands */ +{4, 6}, /* 17 bands */ +{5, 6}, /* 18 bands */ +{5, 6}, /* 19 bands */ +{5, 7}, /* 20 bands */ +{6, 7}, /* 21 bands */ +{6, 7}, /* 22 bands */ +}; + + + + +/*************************************************************************/ +/* ix_max */ +/*************************************************************************/ + +int +ix_max(const int *ix, const int *end) +{ + int max1 = 0, max2 = 0; + + do { + int x1 = *ix++; + int x2 = *ix++; + if (max1 < x1) + max1 = x1; + + if (max2 < x2) + max2 = x2; + } while (ix < end); + if (max1 < max2) + max1 = max2; + return max1; +} + + + + + + + + +int +count_bit_ESC( + const int * ix, + const int * const end, + int t1, + const int t2, + int * const s ) +{ + /* ESC-table is used */ + int linbits = ht[t1].xlen * 65536 + ht[t2].xlen; + int sum = 0, sum2; + + do { + int x = *ix++; + int y = *ix++; + + if (x != 0) { + if (x > 14) { + x = 15; + sum += linbits; + } + x *= 16; + } + + if (y != 0) { + if (y > 14) { + y = 15; + sum += linbits; + } + x += y; + } + + sum += largetbl[x]; + } while (ix < end); + + sum2 = sum & 0xffff; + sum >>= 16; + + if (sum > sum2) { + sum = sum2; + t1 = t2; + } + + *s += sum; + return t1; +} + + +inline static int +count_bit_noESC(const int * ix, const int * const end, int * const s) +{ + /* No ESC-words */ + int sum1 = 0; + const char *hlen1 = ht[1].hlen; + + do { + int x = ix[0] * 2 + ix[1]; + ix += 2; + sum1 += hlen1[x]; + } while (ix < end); + + *s += sum1; + return 1; +} + + + +inline static int +count_bit_noESC_from2( + const int * ix, + const int * const end, + int t1, + int * const s ) +{ + /* No ESC-words */ + unsigned int sum = 0, sum2; + const int xlen = ht[t1].xlen; + const unsigned int *hlen; + if (t1 == 2) + hlen = table23; + else + hlen = table56; + + do { + int x = ix[0] * xlen + ix[1]; + ix += 2; + sum += hlen[x]; + } while (ix < end); + + sum2 = sum & 0xffff; + sum >>= 16; + + if (sum > sum2) { + sum = sum2; + t1++; + } + + *s += sum; + return t1; +} + + +inline static int +count_bit_noESC_from3( + const int * ix, + const int * const end, + int t1, + int * const s ) +{ + /* No ESC-words */ + int sum1 = 0; + int sum2 = 0; + int sum3 = 0; + const int xlen = ht[t1].xlen; + const char *hlen1 = ht[t1].hlen; + const char *hlen2 = ht[t1+1].hlen; + const char *hlen3 = ht[t1+2].hlen; + int t; + + do { + int x = ix[0] * xlen + ix[1]; + ix += 2; + sum1 += hlen1[x]; + sum2 += hlen2[x]; + sum3 += hlen3[x]; + } while (ix < end); + + t = t1; + if (sum1 > sum2) { + sum1 = sum2; + t++; + } + if (sum1 > sum3) { + sum1 = sum3; + t = t1+2; + } + *s += sum1; + + return t; +} + + +/*************************************************************************/ +/* choose table */ +/*************************************************************************/ + +/* + Choose the Huffman table that will encode ix[begin..end] with + the fewest bits. + + Note: This code contains knowledge about the sizes and characteristics + of the Huffman tables as defined in the IS (Table B.7), and will not work + with any arbitrary tables. +*/ + +static int choose_table_nonMMX( + const int * ix, + const int * const end, + int * const s ) +{ + int max; + int choice, choice2; + static const int huf_tbl_noESC[] = { + 1, 2, 5, 7, 7,10,10,13,13,13,13,13,13,13,13 /* char not enough ? */ + }; + + max = ix_max(ix, end); + + switch (max) { + case 0: + return max; + + case 1: + return count_bit_noESC(ix, end, s); + + case 2: + case 3: + return count_bit_noESC_from2(ix, end, huf_tbl_noESC[max - 1], s); + + case 4: case 5: case 6: + case 7: case 8: case 9: + case 10: case 11: case 12: + case 13: case 14: case 15: + return count_bit_noESC_from3(ix, end, huf_tbl_noESC[max - 1], s); + + default: + /* try tables with linbits */ + if (max > IXMAX_VAL) { + *s = LARGE_BITS; + return -1; + } + max -= 15; + for (choice2 = 24; choice2 < 32; choice2++) { + if (ht[choice2].linmax >= max) { + break; + } + } + + for (choice = choice2 - 8; choice < 24; choice++) { + if (ht[choice].linmax >= max) { + break; + } + } + return count_bit_ESC(ix, end, choice, choice2, s); + } +} + + + +/*************************************************************************/ +/* count_bit */ +/*************************************************************************/ + +int count_bits( + lame_internal_flags * const gfc, + int * const ix, + const FLOAT8 * const xr, + gr_info * const gi) +{ + int bits = 0; + int i, a1, a2; + /* since quantize_xrpow uses table lookup, we need to check this first: */ + FLOAT8 w = (IXMAX_VAL) / IPOW20(gi->global_gain); + for ( i = 0; i < 576; i++ ) { + if (xr[i] > w) + return LARGE_BITS; + } + + if (gfc->quantization) + quantize_xrpow(xr, ix, IPOW20(gi->global_gain)); + else + quantize_xrpow_ISO(xr, ix, IPOW20(gi->global_gain)); + + if (gfc->noise_shaping_amp==3) { + int sfb; + // 0.634521682242439 = 0.5946*2**(.5*0.1875) + FLOAT8 roundfac = 0.634521682242439 / IPOW20(gi->global_gain+gi->scalefac_scale); + i = 0; + for (sfb = 0; sfb < gi->sfb_lmax; sfb++) { + int end; + if (!gfc->pseudohalf.l[sfb]) + continue; + + end = gfc->scalefac_band.l[sfb+1]; + for (; i < end; i++) + if (xr[i] < roundfac) + ix[i] = 0; + } + + for (sfb = gi->sfb_smin; sfb < SBPSY_s; sfb++) { + int start, end, win; + start = gfc->scalefac_band.s[sfb]; + end = gfc->scalefac_band.s[sfb+1]; + for (win = 0; win < 3; win++) { + int j; + if (!gfc->pseudohalf.s[sfb][win]) + continue; + for (j = start; j < end; j++, i++) + if (xr[i] < roundfac) + ix[i] = 0; + } + } + } + + + + + + + i=576; + /* Determine count1 region */ + for (; i > 1; i -= 2) + if (ix[i - 1] | ix[i - 2]) + break; + gi->count1 = i; + + /* Determines the number of bits to encode the quadruples. */ + a1 = a2 = 0; + for (; i > 3; i -= 4) { + int p; + /* hack to check if all values <= 1 */ + if ((unsigned int)(ix[i-1] | ix[i-2] | ix[i-3] | ix[i-4]) > 1) + break; + + p = ((ix[i-4] * 2 + ix[i-3]) * 2 + ix[i-2]) * 2 + ix[i-1]; + a1 += t32l[p]; + a2 += t33l[p]; + } + + bits = a1; + gi->count1table_select = 0; + if (a1 > a2) { + bits = a2; + gi->count1table_select = 1; + } + + gi->count1bits = bits; + gi->big_values = i; + if (i == 0) + return bits; + + if (gi->block_type == SHORT_TYPE) { + a1=3*gfc->scalefac_band.s[3]; + if (a1 > gi->big_values) a1 = gi->big_values; + a2 = gi->big_values; + + }else if (gi->block_type == NORM_TYPE) { + assert(i <= 576); /* bv_scf has 576 entries (0..575) */ + a1 = gi->region0_count = gfc->bv_scf[i-2]; + a2 = gi->region1_count = gfc->bv_scf[i-1]; + + assert(a1+a2+2 < SBPSY_l); + a2 = gfc->scalefac_band.l[a1 + a2 + 2]; + a1 = gfc->scalefac_band.l[a1 + 1]; + if (a2 < i) + gi->table_select[2] = gfc->choose_table(ix + a2, ix + i, &bits); + + } else { + gi->region0_count = 7; + /*gi->region1_count = SBPSY_l - 7 - 1;*/ + gi->region1_count = SBMAX_l -1 - 7 - 1; + a1 = gfc->scalefac_band.l[7 + 1]; + a2 = i; + if (a1 > a2) { + a1 = a2; + } + } + + + /* have to allow for the case when bigvalues < region0 < region1 */ + /* (and region0, region1 are ignored) */ + a1 = Min(a1,i); + a2 = Min(a2,i); + + assert( a1 >= 0 ); + assert( a2 >= 0 ); + + /* Count the number of bits necessary to code the bigvalues region. */ + if (0 < a1) + gi->table_select[0] = gfc->choose_table(ix, ix + a1, &bits); + if (a1 < a2) + gi->table_select[1] = gfc->choose_table(ix + a1, ix + a2, &bits); + return bits; +} + +/*********************************************************************** + re-calculate the best scalefac_compress using scfsi + the saved bits are kept in the bit reservoir. + **********************************************************************/ + + +inline static void +recalc_divide_init( + const lame_internal_flags * const gfc, + gr_info cod_info, + int * const ix, + int r01_bits[], + int r01_div [], + int r0_tbl [], + int r1_tbl [] ) +{ + int r0, r1, bigv, r0t, r1t, bits; + + bigv = cod_info.big_values; + + for (r0 = 0; r0 <= 7 + 15; r0++) { + r01_bits[r0] = LARGE_BITS; + } + + for (r0 = 0; r0 < 16; r0++) { + int a1 = gfc->scalefac_band.l[r0 + 1], r0bits; + if (a1 >= bigv) + break; + r0bits = cod_info.part2_length; + r0t = gfc->choose_table(ix, ix + a1, &r0bits); + + for (r1 = 0; r1 < 8; r1++) { + int a2 = gfc->scalefac_band.l[r0 + r1 + 2]; + if (a2 >= bigv) + break; + + bits = r0bits; + r1t = gfc->choose_table(ix + a1, ix + a2, &bits); + if (r01_bits[r0 + r1] > bits) { + r01_bits[r0 + r1] = bits; + r01_div[r0 + r1] = r0; + r0_tbl[r0 + r1] = r0t; + r1_tbl[r0 + r1] = r1t; + } + } + } +} + +inline static void +recalc_divide_sub( + const lame_internal_flags * const gfc, + const gr_info cod_info2, + gr_info * const gi, + const int * const ix, + const int r01_bits[], + const int r01_div [], + const int r0_tbl [], + const int r1_tbl [] ) +{ + int bits, r2, a2, bigv, r2t; + + bigv = cod_info2.big_values; + + for (r2 = 2; r2 < SBMAX_l + 1; r2++) { + a2 = gfc->scalefac_band.l[r2]; + if (a2 >= bigv) + break; + + bits = r01_bits[r2 - 2] + cod_info2.count1bits; + if (gi->part2_3_length <= bits) + break; + + r2t = gfc->choose_table(ix + a2, ix + bigv, &bits); + if (gi->part2_3_length <= bits) + continue; + + memcpy(gi, &cod_info2, sizeof(gr_info)); + gi->part2_3_length = bits; + gi->region0_count = r01_div[r2 - 2]; + gi->region1_count = r2 - 2 - r01_div[r2 - 2]; + gi->table_select[0] = r0_tbl[r2 - 2]; + gi->table_select[1] = r1_tbl[r2 - 2]; + gi->table_select[2] = r2t; + } +} + + + + +void best_huffman_divide( + const lame_internal_flags * const gfc, + gr_info * const gi, + int * const ix ) +{ + int i, a1, a2; + gr_info cod_info2; + + int r01_bits[7 + 15 + 1]; + int r01_div[7 + 15 + 1]; + int r0_tbl[7 + 15 + 1]; + int r1_tbl[7 + 15 + 1]; + + + /* SHORT BLOCK stuff fails for MPEG2 */ + if (gi->block_type == SHORT_TYPE && gfc->mode_gr==1) + return; + + + memcpy(&cod_info2, gi, sizeof(gr_info)); + if (gi->block_type == NORM_TYPE) { + recalc_divide_init(gfc, cod_info2, ix, r01_bits,r01_div,r0_tbl,r1_tbl); + recalc_divide_sub(gfc, cod_info2, gi, ix, r01_bits,r01_div,r0_tbl,r1_tbl); + } + + i = cod_info2.big_values; + if (i == 0 || (unsigned int)(ix[i-2] | ix[i-1]) > 1) + return; + + i = gi->count1 + 2; + if (i > 576) + return; + + /* Determines the number of bits to encode the quadruples. */ + memcpy(&cod_info2, gi, sizeof(gr_info)); + cod_info2.count1 = i; + a1 = a2 = 0; + + assert(i <= 576); + + for (; i > cod_info2.big_values; i -= 4) { + int p = ((ix[i-4] * 2 + ix[i-3]) * 2 + ix[i-2]) * 2 + ix[i-1]; + a1 += t32l[p]; + a2 += t33l[p]; + } + cod_info2.big_values = i; + + cod_info2.count1table_select = 0; + if (a1 > a2) { + a1 = a2; + cod_info2.count1table_select = 1; + } + + cod_info2.count1bits = a1; + cod_info2.part2_3_length = a1 + cod_info2.part2_length; + + if (cod_info2.block_type == NORM_TYPE) + recalc_divide_sub(gfc, cod_info2, gi, ix, r01_bits,r01_div,r0_tbl,r1_tbl); + else { + /* Count the number of bits necessary to code the bigvalues region. */ + a1 = gfc->scalefac_band.l[7 + 1]; + if (a1 > i) { + a1 = i; + } + if (a1 > 0) + cod_info2.table_select[0] = + gfc->choose_table(ix, ix + a1, (int *)&cod_info2.part2_3_length); + if (i > a1) + cod_info2.table_select[1] = + gfc->choose_table(ix + a1, ix + i, (int *)&cod_info2.part2_3_length); + if (gi->part2_3_length > cod_info2.part2_3_length) + memcpy(gi, &cod_info2, sizeof(gr_info)); + } +} + +static const int slen1_n[16] = { 1, 1, 1, 1, 8, 2, 2, 2, 4, 4, 4, 8, 8, 8,16,16 }; +static const int slen2_n[16] = { 1, 2, 4, 8, 1, 2, 4, 8, 2, 4, 8, 2, 4, 8, 4, 8 }; + +void +scfsi_calc(int ch, + III_side_info_t *l3_side, + III_scalefac_t scalefac[2][2]) +{ + int i, s1, s2, c1, c2; + int sfb; + gr_info *gi = &l3_side->gr[1].ch[ch].tt; + + static const int scfsi_band[5] = { 0, 6, 11, 16, 21 }; +#if 0 + static const int slen1_n[16] = { 0, 1, 1, 1, 8, 2, 2, 2, 4, 4, 4, 8, 8, 8,16,16 }; + static const int slen2_n[16] = { 0, 2, 4, 8, 1, 2, 4, 8, 2, 4, 8, 2, 4, 8, 4, 8 }; +#endif + + for (i = 0; i < 4; i++) + l3_side->scfsi[ch][i] = 0; + + for (i = 0; i < (sizeof(scfsi_band) / sizeof(int)) - 1; i++) { + for (sfb = scfsi_band[i]; sfb < scfsi_band[i + 1]; sfb++) { + if (scalefac[0][ch].l[sfb] != scalefac[1][ch].l[sfb]) + break; + } + if (sfb == scfsi_band[i + 1]) { + for (sfb = scfsi_band[i]; sfb < scfsi_band[i + 1]; sfb++) { + scalefac[1][ch].l[sfb] = -1; + } + l3_side->scfsi[ch][i] = 1; + } + } + + s1 = c1 = 0; + for (sfb = 0; sfb < 11; sfb++) { + if (scalefac[1][ch].l[sfb] < 0) + continue; + c1++; + if (s1 < scalefac[1][ch].l[sfb]) + s1 = scalefac[1][ch].l[sfb]; + } + + s2 = c2 = 0; + for (; sfb < SBPSY_l; sfb++) { + if (scalefac[1][ch].l[sfb] < 0) + continue; + c2++; + if (s2 < scalefac[1][ch].l[sfb]) + s2 = scalefac[1][ch].l[sfb]; + } + + for (i = 0; i < 16; i++) { + if (s1 < slen1_n[i] && s2 < slen2_n[i]) { + int c = slen1_tab[i] * c1 + slen2_tab[i] * c2; + if (gi->part2_length > c) { + gi->part2_length = c; + gi->scalefac_compress = i; + } + } + } +} + +/* +Find the optimal way to store the scalefactors. +Only call this routine after final scalefactors have been +chosen and the channel/granule will not be re-encoded. + */ +void best_scalefac_store( + const lame_internal_flags *gfc, + const int gr, + const int ch, + int l3_enc[2][2][576], + III_side_info_t * const l3_side, + III_scalefac_t scalefac[2][2] ) +{ + + /* use scalefac_scale if we can */ + gr_info *gi = &l3_side->gr[gr].ch[ch].tt; + int sfb,i,j,j2,l,start,end; + + /* remove scalefacs from bands with ix=0. This idea comes + * from the AAC ISO docs. added mt 3/00 */ + /* check if l3_enc=0 */ + for ( sfb = 0; sfb < gi->sfb_lmax; sfb++ ) { + if (scalefac[gr][ch].l[sfb]>0) { + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + for ( l = start; l < end; l++ ) if (l3_enc[gr][ch][l]!=0) break; + if (l==end) scalefac[gr][ch].l[sfb]=0; + } + } + for ( j=0, sfb = gi->sfb_smin; sfb < SBPSY_s; sfb++ ) { + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb+1 ]; + for ( i = 0; i < 3; i++ ) { + if (scalefac[gr][ch].s[sfb][i]>0) { + j2 = j; + for ( l = start; l < end; l++ ) + if (l3_enc[gr][ch][j2++ /*3*l+i*/]!=0) break; + if (l==end) scalefac[gr][ch].s[sfb][i]=0; + } + j += end-start; + } + } + + + gi->part2_3_length -= gi->part2_length; + if (!gi->scalefac_scale && !gi->preflag) { + int b, s = 0; + for (sfb = 0; sfb < gi->sfb_lmax; sfb++) { + s |= scalefac[gr][ch].l[sfb]; + } + + for (sfb = gi->sfb_smin; sfb < SBPSY_s; sfb++) { + for (b = 0; b < 3; b++) { + s |= scalefac[gr][ch].s[sfb][b]; + } + } + + if (!(s & 1) && s != 0) { + for (sfb = 0; sfb < gi->sfb_lmax; sfb++) { + scalefac[gr][ch].l[sfb] /= 2; + } + for (sfb = gi->sfb_smin; sfb < SBPSY_s; sfb++) { + for (b = 0; b < 3; b++) { + scalefac[gr][ch].s[sfb][b] /= 2; + } + } + + gi->scalefac_scale = 1; + gi->part2_length = 99999999; + if (gfc->mode_gr == 2) { + scale_bitcount(&scalefac[gr][ch], gi); + } else { + scale_bitcount_lsf(gfc,&scalefac[gr][ch], gi); + } + } + } + + + for ( i = 0; i < 4; i++ ) + l3_side->scfsi[ch][i] = 0; + + if (gfc->mode_gr==2 && gr == 1 + && l3_side->gr[0].ch[ch].tt.block_type != SHORT_TYPE + && l3_side->gr[1].ch[ch].tt.block_type != SHORT_TYPE) { + scfsi_calc(ch, l3_side, scalefac); + } + gi->part2_3_length += gi->part2_length; +} + + +/* number of bits used to encode scalefacs */ + +/* 18*slen1_tab[i] + 18*slen2_tab[i] */ +static const int scale_short[16] = { + 0, 18, 36, 54, 54, 36, 54, 72, 54, 72, 90, 72, 90, 108, 108, 126 }; + +/* 17*slen1_tab[i] + 18*slen2_tab[i] */ +static const int scale_mixed[16] = { + 0, 18, 36, 54, 51, 35, 53, 71, 52, 70, 88, 69, 87, 105, 104, 122 }; + +/* 11*slen1_tab[i] + 10*slen2_tab[i] */ +static const int scale_long[16] = { + 0, 10, 20, 30, 33, 21, 31, 41, 32, 42, 52, 43, 53, 63, 64, 74 }; + + +/*************************************************************************/ +/* scale_bitcount */ +/*************************************************************************/ + +/* Also calculates the number of bits necessary to code the scalefactors. */ + +int scale_bitcount( + III_scalefac_t * const scalefac, gr_info * const cod_info) +{ + int i, k, sfb, max_slen1 = 0, max_slen2 = 0, ep = 2; + + /* maximum values */ + const int *tab; + + + if ( cod_info->block_type == SHORT_TYPE ) { + tab = scale_short; + if (cod_info->mixed_block_flag) { + tab = scale_mixed; + for ( sfb = 0 ; sfb < cod_info->sfb_lmax; sfb++ ) + if (max_slen1 < scalefac->l[sfb]) + max_slen1 = scalefac->l[sfb]; + } + + for ( i = 0; i < 3; i++ ) { + for ( sfb = cod_info->sfb_smin; sfb < 6; sfb++ ) + if (max_slen1 < scalefac->s[sfb][i]) + max_slen1 = scalefac->s[sfb][i]; + for (sfb = 6; sfb < SBPSY_s; sfb++ ) + if (max_slen2 < scalefac->s[sfb][i]) + max_slen2 = scalefac->s[sfb][i]; + } + } + else + { /* block_type == 1,2,or 3 */ + tab = scale_long; + for ( sfb = 0; sfb < 11; sfb++ ) + if ( scalefac->l[sfb] > max_slen1 ) + max_slen1 = scalefac->l[sfb]; + + if (!cod_info->preflag) { + for ( sfb = 11; sfb < SBPSY_l; sfb++ ) + if (scalefac->l[sfb] < pretab[sfb]) + break; + + if (sfb == SBPSY_l) { + cod_info->preflag = 1; + for ( sfb = 11; sfb < SBPSY_l; sfb++ ) + scalefac->l[sfb] -= pretab[sfb]; + } + } + + for ( sfb = 11; sfb < SBPSY_l; sfb++ ) + if ( scalefac->l[sfb] > max_slen2 ) + max_slen2 = scalefac->l[sfb]; + } + + + /* from Takehiro TOMINAGA 10/99 + * loop over *all* posible values of scalefac_compress to find the + * one which uses the smallest number of bits. ISO would stop + * at first valid index */ + cod_info->part2_length = LARGE_BITS; + for ( k = 0; k < 16; k++ ) + { + if ( (max_slen1 < slen1_n[k]) && (max_slen2 < slen2_n[k]) && + (cod_info->part2_length > tab[k])) { + cod_info->part2_length=tab[k]; + cod_info->scalefac_compress=k; + ep=0; /* we found a suitable scalefac_compress */ + } + } + return ep; +} + + + +/* + table of largest scalefactor values for MPEG2 +*/ +static const int max_range_sfac_tab[6][4] = +{ + { 15, 15, 7, 7}, + { 15, 15, 7, 0}, + { 7, 3, 0, 0}, + { 15, 31, 31, 0}, + { 7, 7, 7, 0}, + { 3, 3, 0, 0} +}; + + + + +/*************************************************************************/ +/* scale_bitcount_lsf */ +/*************************************************************************/ + +/* Also counts the number of bits to encode the scalefacs but for MPEG 2 */ +/* Lower sampling frequencies (24, 22.05 and 16 kHz.) */ + +/* This is reverse-engineered from section 2.4.3.2 of the MPEG2 IS, */ +/* "Audio Decoding Layer III" */ + +int scale_bitcount_lsf(const lame_internal_flags *gfc, + const III_scalefac_t * const scalefac, gr_info * const cod_info) +{ + int table_number, row_in_table, partition, nr_sfb, window, over; + int i, sfb, max_sfac[ 4 ]; + const int *partition_table; + + /* + Set partition table. Note that should try to use table one, + but do not yet... + */ + if ( cod_info->preflag ) + table_number = 2; + else + table_number = 0; + + for ( i = 0; i < 4; i++ ) + max_sfac[i] = 0; + + if ( cod_info->block_type == SHORT_TYPE ) + { + row_in_table = 1; + partition_table = &nr_of_sfb_block[table_number][row_in_table][0]; + for ( sfb = 0, partition = 0; partition < 4; partition++ ) + { + nr_sfb = partition_table[ partition ] / 3; + for ( i = 0; i < nr_sfb; i++, sfb++ ) + for ( window = 0; window < 3; window++ ) + if ( scalefac->s[sfb][window] > max_sfac[partition] ) + max_sfac[partition] = scalefac->s[sfb][window]; + } + } + else + { + row_in_table = 0; + partition_table = &nr_of_sfb_block[table_number][row_in_table][0]; + for ( sfb = 0, partition = 0; partition < 4; partition++ ) + { + nr_sfb = partition_table[ partition ]; + for ( i = 0; i < nr_sfb; i++, sfb++ ) + if ( scalefac->l[sfb] > max_sfac[partition] ) + max_sfac[partition] = scalefac->l[sfb]; + } + } + + for ( over = 0, partition = 0; partition < 4; partition++ ) + { + if ( max_sfac[partition] > max_range_sfac_tab[table_number][partition] ) + over++; + } + if ( !over ) + { + /* + Since no bands have been over-amplified, we can set scalefac_compress + and slen[] for the formatter + */ + static const int log2tab[] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 }; + + int slen1, slen2, slen3, slen4; + + cod_info->sfb_partition_table = nr_of_sfb_block[table_number][row_in_table]; + for ( partition = 0; partition < 4; partition++ ) + cod_info->slen[partition] = log2tab[max_sfac[partition]]; + + /* set scalefac_compress */ + slen1 = cod_info->slen[ 0 ]; + slen2 = cod_info->slen[ 1 ]; + slen3 = cod_info->slen[ 2 ]; + slen4 = cod_info->slen[ 3 ]; + + switch ( table_number ) + { + case 0: + cod_info->scalefac_compress = (((slen1 * 5) + slen2) << 4) + + (slen3 << 2) + + slen4; + break; + + case 1: + cod_info->scalefac_compress = 400 + + (((slen1 * 5) + slen2) << 2) + + slen3; + break; + + case 2: + cod_info->scalefac_compress = 500 + (slen1 * 3) + slen2; + break; + + default: + ERRORF(gfc,"intensity stereo not implemented yet\n" ); + break; + } + } +#ifdef DEBUG + if ( over ) + ERRORF(gfc, "---WARNING !! Amplification of some bands over limits\n" ); +#endif + if (!over) { + assert( cod_info->sfb_partition_table ); + cod_info->part2_length=0; + for ( partition = 0; partition < 4; partition++ ) + cod_info->part2_length += cod_info->slen[partition] * cod_info->sfb_partition_table[partition]; + } + return over; +} + + + +void huffman_init(lame_internal_flags * const gfc) +{ + int i; + + gfc->choose_table = choose_table_nonMMX; + +#ifdef MMX_choose_table + if (gfc->CPU_features.MMX) { + extern int choose_table_MMX(const int *ix, const int *end, int *s); + gfc->choose_table = choose_table_MMX; + } +#endif + + for (i = 2; i <= 576; i += 2) { + int scfb_anz = 0, index; + while (gfc->scalefac_band.l[++scfb_anz] < i) + ; + + index = subdv_table[scfb_anz].region0_count; + while (gfc->scalefac_band.l[index + 1] > i) + index--; + + if (index < 0) { + /* this is an indication that everything is going to + be encoded as region0: bigvalues < region0 < region1 + so lets set region0, region1 to some value larger + than bigvalues */ + index = subdv_table[scfb_anz].region0_count; + } + + gfc->bv_scf[i-2] = index; + + index = subdv_table[scfb_anz].region1_count; + while (gfc->scalefac_band.l[index + gfc->bv_scf[i-2] + 2] > i) + index--; + + if (index < 0) { + index = subdv_table[scfb_anz].region1_count; + } + + gfc->bv_scf[i-1] = index; + } +} diff --git a/lib/lame/tools.h b/lib/lame/tools.h new file mode 100644 index 0000000..e8c6de3 --- /dev/null +++ b/lib/lame/tools.h @@ -0,0 +1,101 @@ +/* + * LAME tools library include file + * Simple context free functions + * - no references to gfc, to gfp, or to any other function not defined + * in this module + * + * Copyright (c) 2000 Frank Klemm + * Copyright (c) 2001 John Dahlstrom + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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: tools.h,v 1.1 2002/04/28 17:30:30 kramm Exp $ */ + +#ifndef LAME_TOOLS_H +#define LAME_TOOLS_H + +#include "machine.h" + + + +/*********************************************************************** +* Function Prototype Declarations +***********************************************************************/ + +static inline void qinterp_cf_42( const FLOAT y[4], FLOAT c[3] ); +static inline void qinterp_cf_3( const FLOAT y[3], FLOAT c[3] ); +static inline FLOAT qinterp_eval( const FLOAT c[3], FLOAT x, + FLOAT xtrans, FLOAT xratio ); + + + +/*********************************************************************** +* Macros and Static Inline Function Definitions +***********************************************************************/ + +/* qinterp_cf_42 - Given 4 points, find the coefficients for a quadratic + that connects the 2 center points. -jd + in: y coordinate values, paired with constant x coordinates, -1, 0, 1, 2 + out: c coefficients ordered for quadratic, (c[2] * x*x + c[1] * x + c[0]) +design note: + Utilize the inverse of two constant 3x3 matrices to compute two quadratics, + one from the points at (-1,0,1), and the other from the points at (0,1,2). + The mean of the two yields a quadratic between the points at 0 and 1. +*/ +static inline void +qinterp_cf_42( const FLOAT y[4], FLOAT c[3] ) +{ + c[2] = ( y[0] - y[1] - y[2] + y[3]) * 0.25; /* ([1 -1 -1 1] .* Y) * 0.25 */ + c[1] = y[2] - y[1] - c[2]; /* ([-1 -3 5 -1] .* Y) * 0.25 */ + c[0] = y[1]; +} + +/* qinterp_cf_3 - Given 3 points, find the coefficients for a quadratic + that connects the 3 points. -jd + in: y coordinate values, paired with constant x coordinates, 0, 1, 2 + out: c coefficients ordered for quadratic, (c[2] * x*x + c[1] * x + c[0]) +*/ +static inline void +qinterp_cf_3( const FLOAT y[3], FLOAT c[3] ) +{ + c[2] = ( y[0] + y[2]) * 0.5 - y[1]; /* ([1 -2 1] .* Y) * 0.5 */ + c[1] = y[1] - y[0] - c[2]; /* ([-3 4 -1] .* Y) * 0.5 */ + c[0] = y[0]; +} + + + +/* qinterp_eval - Evaluate a quadratic at a point, given polynomial + coefficients, and an x coordinate with translation and scale + ratio values. This function evaluates the quadratic at the + transformed x coordinate ((x - xtrans) * xratio)). -jd + in: c quadratic coefficients, for (c[2] * x * x + c[1] * x + c[0]) + x + xtrans + xratio +returns: y coordinate (the quadratic evaluated) +*/ +static inline FLOAT +qinterp_eval( const FLOAT c[3], FLOAT x, FLOAT xtrans, FLOAT xratio ) +{ + x = (x - xtrans) * xratio; + return( (c[2] * x + c[1]) * x + c[0] ); +} + + + +#endif /* LAME_TOOLS_H */ diff --git a/lib/lame/util.c b/lib/lame/util.c new file mode 100644 index 0000000..1df7de1 --- /dev/null +++ b/lib/lame/util.c @@ -0,0 +1,989 @@ +/* + * lame utility library source file + * + * Copyright (c) 1999 Albert L Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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: util.c,v 1.1 2002/04/28 17:30:30 kramm Exp $ */ + +#include "config_static.h" + +#define PRECOMPUTE + +#include "util.h" +#include "tools.h" +#include +#include +#include + +#if defined(__FreeBSD__) && !defined(__alpha__) +# include +#endif + +#ifdef WITH_DMALLOC +#include +#endif + +/*********************************************************************** +* +* Global Function Definitions +* +***********************************************************************/ +/*empty and close mallocs in gfc */ + +void freegfc ( lame_internal_flags* const gfc ) /* bit stream structure */ +{ + int i; + +#ifdef KLEMM_44 + if (gfc->resample_in != NULL) { + resample_close(gfc->resample_in); + gfc->resample_in = NULL; + } + free(gfc->mfbuf[0]); + free(gfc->mfbuf[1]); +#endif + + for ( i = 0 ; i <= 2*BPC; i++ ) + if ( gfc->blackfilt[i] != NULL ) { + free ( gfc->blackfilt[i] ); + gfc->blackfilt[i] = NULL; + } + if ( gfc->inbuf_old[0] ) { + free ( gfc->inbuf_old[0] ); + gfc->inbuf_old[0] = NULL; + } + if ( gfc->inbuf_old[1] ) { + free ( gfc->inbuf_old[1] ); + gfc->inbuf_old[1] = NULL; + } + + if ( gfc->bs.buf != NULL ) { + free ( gfc->bs.buf ); + gfc->bs.buf = NULL; + } + + if ( gfc->VBR_seek_table.bag ) { + free ( gfc->VBR_seek_table.bag ); + } + if ( gfc->ATH ) { + free ( gfc->ATH ); + } + if ( gfc->VBR ) { + free ( gfc->VBR ); + } + if ( gfc->PSY ) { + free ( gfc->PSY ); + } + if ( gfc->s3_ll ) { + /* XXX allocated in psymodel_init() */ + free ( gfc->s3_ll ); + } + if ( gfc->s3_ss ) { + /* XXX allocated in psymodel_init() */ + free ( gfc->s3_ss ); + } + free ( gfc ); +} + + + +/*those ATH formulas are returning +their minimum value for input = -1*/ + +FLOAT8 ATHformula_GB(FLOAT8 f, FLOAT8 value) +{ + /* from Painter & Spanias + modified by Gabriel Bouvigne to better fit the reality + ath = 3.640 * pow(f,-0.8) + - 6.800 * exp(-0.6*pow(f-3.4,2.0)) + + 6.000 * exp(-0.15*pow(f-8.7,2.0)) + + 0.6* 0.001 * pow(f,4.0); + + + In the past LAME was using the Painter &Spanias formula. + But we had some recurrent problems with HF content. + We measured real ATH values, and found the older formula + to be inacurate in the higher part. So we made this new + formula and this solved most of HF problematic testcases. + The tradeoff is that in VBR mode it increases a lot the + bitrate.*/ + + +/*this curve can be udjusted according to the VBR scale: +it adjusts from something close to Painter & Spanias +on V9 up to Bouvigne's formula for V0. This way the VBR +bitrate is more balanced according to the -V value.*/ + + FLOAT8 ath; + + if (f < -.3) + f=3410; + + f /= 1000; // convert to khz + f = Max(0.01, f); + f = Min(18.0, f); + + ath = 3.640 * pow(f,-0.8) + - 6.800 * exp(-0.6*pow(f-3.4,2.0)) + + 6.000 * exp(-0.15*pow(f-8.7,2.0)) + + (0.6+0.04*value)* 0.001 * pow(f,4.0); + return ath; +} + + +/* + * Klemm 1994 and 1997. Experimental data. Sorry, data looks a little bit + * dodderly. Data below 30 Hz is extrapolated from other material, above 18 + * kHz the ATH is limited due to the original purpose (too much noise at + * ATH is not good even if it's theoretically inaudible). + */ + +FLOAT8 ATHformula_Frank( FLOAT8 freq ) +{ + /* + * one value per 100 cent = 1 + * semitone = 1/4 + * third = 1/12 + * octave = 1/40 decade + * rest is linear interpolated, values are currently in decibel rel. 20 µPa + */ + static FLOAT tab [] = { + /* 10.0 */ 96.69, 96.69, 96.26, 95.12, + /* 12.6 */ 93.53, 91.13, 88.82, 86.76, + /* 15.8 */ 84.69, 82.43, 79.97, 77.48, + /* 20.0 */ 74.92, 72.39, 70.00, 67.62, + /* 25.1 */ 65.29, 63.02, 60.84, 59.00, + /* 31.6 */ 57.17, 55.34, 53.51, 51.67, + /* 39.8 */ 50.04, 48.12, 46.38, 44.66, + /* 50.1 */ 43.10, 41.73, 40.50, 39.22, + /* 63.1 */ 37.23, 35.77, 34.51, 32.81, + /* 79.4 */ 31.32, 30.36, 29.02, 27.60, + /* 100.0 */ 26.58, 25.91, 24.41, 23.01, + /* 125.9 */ 22.12, 21.25, 20.18, 19.00, + /* 158.5 */ 17.70, 16.82, 15.94, 15.12, + /* 199.5 */ 14.30, 13.41, 12.60, 11.98, + /* 251.2 */ 11.36, 10.57, 9.98, 9.43, + /* 316.2 */ 8.87, 8.46, 7.44, 7.12, + /* 398.1 */ 6.93, 6.68, 6.37, 6.06, + /* 501.2 */ 5.80, 5.55, 5.29, 5.02, + /* 631.0 */ 4.75, 4.48, 4.22, 3.98, + /* 794.3 */ 3.75, 3.51, 3.27, 3.22, + /* 1000.0 */ 3.12, 3.01, 2.91, 2.68, + /* 1258.9 */ 2.46, 2.15, 1.82, 1.46, + /* 1584.9 */ 1.07, 0.61, 0.13, -0.35, + /* 1995.3 */ -0.96, -1.56, -1.79, -2.35, + /* 2511.9 */ -2.95, -3.50, -4.01, -4.21, + /* 3162.3 */ -4.46, -4.99, -5.32, -5.35, + /* 3981.1 */ -5.13, -4.76, -4.31, -3.13, + /* 5011.9 */ -1.79, 0.08, 2.03, 4.03, + /* 6309.6 */ 5.80, 7.36, 8.81, 10.22, + /* 7943.3 */ 11.54, 12.51, 13.48, 14.21, + /* 10000.0 */ 14.79, 13.99, 12.85, 11.93, + /* 12589.3 */ 12.87, 15.19, 19.14, 23.69, + /* 15848.9 */ 33.52, 48.65, 59.42, 61.77, + /* 19952.6 */ 63.85, 66.04, 68.33, 70.09, + /* 25118.9 */ 70.66, 71.27, 71.91, 72.60, + }; + FLOAT8 freq_log; + unsigned index; + + if (freq < -.3) + freq=3758; + + if ( freq < 10. ) freq = 10.; + if ( freq > 29853. ) freq = 29853.; + + freq_log = 40. * log10 (0.1 * freq); /* 4 steps per third, starting at 10 Hz */ + index = (unsigned) freq_log; + assert ( index < sizeof(tab)/sizeof(*tab) ); + return tab [index] * (1 + index - freq_log) + tab [index+1] * (freq_log - index); +} + + + +/* ATHformula_jd - Compute ATH at a given frequency from experimental data. + Below 15000 Hz, this ATH curve is based on data merged from + various existing sources. New experimental data covers + frequencies above 15000 Hz. -jd + in: freq (Hz) +returns: ATH value at freq in dB, or minimum ATH value if input freq is -1 +design notes: + Above 15000 Hz, my data indicates roughly 10 dB between the edge of + ready detection, and statistical indistinguishability. To provide a + balance between my data, and ATH data from other sources, roughly 5 dB + is added above 15000 Hz, except at frequencies above 20500 Hz. The ATH + of 21000+ Hz frequencies is decreased by 5 dB, to reduce the possibility + of extra distortion that some output systems exhibit when given a contrived + sample with an intense, but hardly audible frequency. +*/ +FLOAT8 +ATHformula_jd( FLOAT8 freq ) +{ + int i; + int ifreq; + int at_i; + int tstep; + int xtrans; + FLOAT coeff[3]; + FLOAT8 rval; + + const FLOAT ath_lt100[] /* 20 - 120 Hz (for computing 0 - 100 Hz) */ + = { 74.0, 47.9, 35.2, 28.1, 23.5, 20.4 }; + + const FLOAT ath_lt500[] /* 100 - 600 Hz (for 100 - 500 Hz) */ + = { 23.5, 13.4, 9.4, 6.9, 5.9, 5.0 }; + + const FLOAT ath_gt500[] /* 500 Hz and above */ + = { /* 500 */ 5.9, 3.2, 1.6, -0.7, + /* 2500 */ -2.7, -4.5, -5.2, -4.8, -3.7, + /* 5000 */ -1.6, 1.5, 3.8, 5.3, 6.8, + /* 7500 */ 8.2, 9.5, 10.5, 11.3, 11.8, + /* 10000 */ 12.1, 12.2, 12.4, 12.4, 12.4, + /* 12500 */ 12.8, 13.5, 14.9, 16.8, 19.0, + /* 15000 */ 23.0, 27.0, 33.0, 36.5, 39.5, + /* 17500 */ 43.5, 51.5, 58.5, 65.0, 71.5, + /* 20000 */ 78.0, 79.5, 80.0, 80.5, 80.5, 80.5 }; + + const FLOAT *ath_table[4]; + const int ath_table_step[4] = { 20, 100, 500, 500 }; + const FLOAT ath_table_xratio[4] = { 0.05, 0.01, 0.002, 0.002 }; + + ath_table[0] = ath_lt100; + ath_table[1] = ath_lt500; + ath_table[3] = ath_gt500; + + if( freq >= -0.5 && freq < 22000 ) { + ifreq = (int) freq; + at_i = ( (((99 - ifreq) >> (sizeof(int) * 8 - 1)) & 0x1) + | (((499 - ifreq) >> (sizeof(int) * 8 - 2)) & 0x3) ); + tstep = ath_table_step[at_i]; + + i = (ifreq / tstep); + i -= 2; + if( i >= 0 ) { + qinterp_cf_42( ath_table[at_i] + i, coeff ); + xtrans = (i + 2) * tstep; + } else { /* leading edge */ + qinterp_cf_3( ath_table[at_i], coeff ); + xtrans = tstep; + } + rval = qinterp_eval( coeff, freq, (FLOAT)xtrans, ath_table_xratio[at_i]); + return(rval); + } else if( freq < 0 ) { + return(-5.2); /* minimum value from table */ + } else { + return( ath_gt500[ 22000 / 500 - 1 ] ); /* 22kHz ATH used for 22kHz+ */ + } +} + + + +FLOAT8 ATHformula(FLOAT8 f,lame_global_flags *gfp) +{ + switch(gfp->ATHtype) + { + case 0: + return ATHformula_GB(f, 9); + case 1: + return ATHformula_Frank(f); + case 2: + return ATHformula_GB(f, 0); + case 3: + return ATHformula_GB(f, 1) +6; /*modification of GB formula by Roel*/ + case 4: + if (!(gfp->VBR == vbr_off || gfp->VBR == vbr_abr)) /*this case should be used with true vbr only*/ + return ATHformula_GB(f,gfp->VBR_q); + case 5: + return ATHformula_jd(f); + } + + return ATHformula_GB(f, 0); +} + +/* see for example "Zwicker: Psychoakustik, 1982; ISBN 3-540-11401-7 */ +FLOAT8 freq2bark(FLOAT8 freq) +{ + /* input: freq in hz output: barks */ + if (freq<0) freq=0; + freq = freq * 0.001; + return 13.0*atan(.76*freq) + 3.5*atan(freq*freq/(7.5*7.5)); +} + +/* see for example "Zwicker: Psychoakustik, 1982; ISBN 3-540-11401-7 */ +FLOAT8 freq2cbw(FLOAT8 freq) +{ + /* input: freq in hz output: critical band width */ + freq = freq * 0.001; + return 25+75*pow(1+1.4*(freq*freq),0.69); +} + + + + + + +/*********************************************************************** + * compute bitsperframe and mean_bits for a layer III frame + **********************************************************************/ +void getframebits(const lame_global_flags * gfp, int *bitsPerFrame, int *mean_bits) +{ + lame_internal_flags *gfc=gfp->internal_flags; + int whole_SpF; /* integral number of Slots per Frame without padding */ + int bit_rate; + + /* get bitrate in kbps [?] */ + if (gfc->bitrate_index) + bit_rate = bitrate_table[gfp->version][gfc->bitrate_index]; + else + bit_rate = gfp->brate; + assert ( bit_rate <= 550 ); + + // bytes_per_frame = bitrate * 1000 / ( gfp->out_samplerate / (gfp->version == 1 ? 1152 : 576 )) / 8; + // bytes_per_frame = bitrate * 1000 / gfp->out_samplerate * (gfp->version == 1 ? 1152 : 576 ) / 8; + // bytes_per_frame = bitrate * ( gfp->version == 1 ? 1152/8*1000 : 576/8*1000 ) / gfp->out_samplerate; + + whole_SpF = (gfp->version+1)*72000*bit_rate / gfp->out_samplerate; + + /* main encoding routine toggles padding on and off */ + /* one Layer3 Slot consists of 8 bits */ + *bitsPerFrame = 8 * (whole_SpF + gfc->padding); + + // sideinfo_len + *mean_bits = (*bitsPerFrame - 8*gfc->sideinfo_len) / gfc->mode_gr; +} + + + + +#define ABS(A) (((A)>0) ? (A) : -(A)) + +int FindNearestBitrate( +int bRate, /* legal rates from 32 to 448 */ +int version, /* MPEG-1 or MPEG-2 LSF */ +int samplerate) /* convert bitrate in kbps to index */ +{ + int bitrate = 0; + int i; + + for ( i = 1; i <= 14; i++ ) + if ( ABS (bitrate_table[version][i] - bRate) < ABS (bitrate - bRate) ) + bitrate = bitrate_table [version] [i]; + + return bitrate; +} + + +/* map frequency to a valid MP3 sample frequency + * + * Robert.Hegemann@gmx.de 2000-07-01 + */ +int map2MP3Frequency(int freq) +{ + if (freq <= 8000) return 8000; + if (freq <= 11025) return 11025; + if (freq <= 12000) return 12000; + if (freq <= 16000) return 16000; + if (freq <= 22050) return 22050; + if (freq <= 24000) return 24000; + if (freq <= 32000) return 32000; + if (freq <= 44100) return 44100; + + return 48000; +} + +int BitrateIndex( +int bRate, /* legal rates from 32 to 448 kbps */ +int version, /* MPEG-1 or MPEG-2/2.5 LSF */ +int samplerate) /* convert bitrate in kbps to index */ +{ + int i; + + for ( i = 0; i <= 14; i++) + if ( bitrate_table [version] [i] == bRate ) + return i; + + return -1; +} + +/* convert samp freq in Hz to index */ + +int SmpFrqIndex ( int sample_freq, int* const version ) +{ + switch ( sample_freq ) { + case 44100: *version = 1; return 0; + case 48000: *version = 1; return 1; + case 32000: *version = 1; return 2; + case 22050: *version = 0; return 0; + case 24000: *version = 0; return 1; + case 16000: *version = 0; return 2; + case 11025: *version = 0; return 0; + case 12000: *version = 0; return 1; + case 8000: *version = 0; return 2; + default: *version = 0; return -1; + } +} + + +/***************************************************************************** +* +* End of bit_stream.c package +* +*****************************************************************************/ + +/* reorder the three short blocks By Takehiro TOMINAGA */ +/* + Within each scalefactor band, data is given for successive + time windows, beginning with window 0 and ending with window 2. + Within each window, the quantized values are then arranged in + order of increasing frequency... +*/ +void freorder(int scalefac_band[],FLOAT8 ix_orig[576]) { + int i,sfb, window, j=0; + FLOAT8 ix[576]; + for (sfb = 0; sfb < SBMAX_s; sfb++) { + int start = scalefac_band[sfb]; + int end = scalefac_band[sfb + 1]; + for (window = 0; window < 3; window++) { + for (i = start; i < end; ++i) { + ix[j++] = ix_orig[3*i+window]; + } + } + } + memcpy(ix_orig,ix,576*sizeof(FLOAT8)); +} + + + + + + + +#ifndef KLEMM_44 + + +/* resampling via FIR filter, blackman window */ +inline static FLOAT8 blackman(FLOAT8 x,FLOAT8 fcn,int l) +{ + /* This algorithm from: +SIGNAL PROCESSING ALGORITHMS IN FORTRAN AND C +S.D. Stearns and R.A. David, Prentice-Hall, 1992 + */ + FLOAT8 bkwn,x2; + FLOAT8 wcn = (PI * fcn); + + x /= l; + if (x<0) x=0; + if (x>1) x=1; + x2 = x - .5; + + bkwn = 0.42 - 0.5*cos(2*x*PI) + 0.08*cos(4*x*PI); + if (fabs(x2)<1e-9) return wcn/PI; + else + return ( bkwn*sin(l*wcn*x2) / (PI*l*x2) ); + + +} + +/* gcd - greatest common divisor */ +/* Joint work of Euclid and M. Hendry */ + +int gcd ( int i, int j ) +{ +// assert ( i > 0 && j > 0 ); + return j ? gcd(j, i % j) : i; +} + + + +/* copy in new samples from in_buffer into mfbuf, with resampling & scaling + if necessary. n_in = number of samples from the input buffer that + were used. n_out = number of samples copied into mfbuf */ + +void fill_buffer(lame_global_flags *gfp, + sample_t *mfbuf[2], + sample_t *in_buffer[2], + int nsamples, int *n_in, int *n_out) +{ + lame_internal_flags *gfc = gfp->internal_flags; + int ch,i; + + /* copy in new samples into mfbuf, with resampling if necessary */ + if (gfc->resample_ratio != 1.0) { + for (ch = 0; ch < gfc->channels_out; ch++) { + *n_out = + fill_buffer_resample(gfp, &mfbuf[ch][gfc->mf_size], + gfp->framesize, in_buffer[ch], + nsamples, n_in, ch); + } + } + else { + *n_out = Min(gfp->framesize, nsamples); + *n_in = *n_out; + for (i = 0; i < *n_out; ++i) { + mfbuf[0][gfc->mf_size + i] = in_buffer[0][i]; + if (gfc->channels_out == 2) + mfbuf[1][gfc->mf_size + i] = in_buffer[1][i]; + } + } + + /* user selected scaling of the samples */ + if (gfp->scale != 0 && gfp->scale != 1.0) { + for (i=0 ; i<*n_out; ++i) { + mfbuf[0][gfc->mf_size+i] *= gfp->scale; + if (gfc->channels_out == 2) + mfbuf[1][gfc->mf_size + i] *= gfp->scale; + } + } + + /* user selected scaling of the channel 0 (left) samples */ + if (gfp->scale_left != 0 && gfp->scale_left != 1.0) { + for (i=0 ; i<*n_out; ++i) { + mfbuf[0][gfc->mf_size+i] *= gfp->scale_left; + } + } + + /* user selected scaling of the channel 1 (right) samples */ + if (gfc->channels_out == 2) { + if (gfp->scale_right != 0 && gfp->scale_right != 1.0) { + for (i=0 ; i<*n_out; ++i) { + mfbuf[1][gfc->mf_size + i] *= gfp->scale_right; + } + } + } +} + + + + +int fill_buffer_resample( + lame_global_flags *gfp, + sample_t *outbuf, + int desired_len, + sample_t *inbuf, + int len, + int *num_used, + int ch) +{ + + + lame_internal_flags *gfc=gfp->internal_flags; + int BLACKSIZE; + FLOAT8 offset,xvalue; + int i,j=0,k; + int filter_l; + FLOAT8 fcn,intratio; + FLOAT *inbuf_old; + int bpc; /* number of convolution functions to pre-compute */ + bpc = gfp->out_samplerate/gcd(gfp->out_samplerate,gfp->in_samplerate); + if (bpc>BPC) bpc = BPC; + + intratio=( fabs(gfc->resample_ratio - floor(.5+gfc->resample_ratio)) < .0001 ); + fcn = 1.00/gfc->resample_ratio; + if (fcn>1.00) fcn=1.00; + filter_l = gfp->quality < 7 ? 31 : 7; + filter_l = 31; + if (0==filter_l % 2 ) --filter_l;/* must be odd */ + filter_l += intratio; /* unless resample_ratio=int, it must be even */ + + + BLACKSIZE = filter_l+1; /* size of data needed for FIR */ + + if ( gfc->fill_buffer_resample_init == 0 ) { + gfc->inbuf_old[0]=calloc(BLACKSIZE,sizeof(gfc->inbuf_old[0][0])); + gfc->inbuf_old[1]=calloc(BLACKSIZE,sizeof(gfc->inbuf_old[0][0])); + for (i=0; i<=2*bpc; ++i) + gfc->blackfilt[i]=calloc(BLACKSIZE,sizeof(gfc->blackfilt[0][0])); + + gfc->itime[0]=0; + gfc->itime[1]=0; + + /* precompute blackman filter coefficients */ + for ( j = 0; j <= 2*bpc; j++ ) { + FLOAT8 sum = 0.; + offset = (j-bpc) / (2.*bpc); + for ( i = 0; i <= filter_l; i++ ) + sum += + gfc->blackfilt[j][i] = blackman(i-offset,fcn,filter_l); + for ( i = 0; i <= filter_l; i++ ) + gfc->blackfilt[j][i] /= sum; + } + gfc->fill_buffer_resample_init = 1; + } + + inbuf_old=gfc->inbuf_old[ch]; + + /* time of j'th element in inbuf = itime + j/ifreq; */ + /* time of k'th element in outbuf = j/ofreq */ + for (k=0;kresample_ratio; /* time of k'th output sample */ + j = floor( time0 -gfc->itime[ch] ); + + /* check if we need more input data */ + if ((filter_l + j - filter_l/2) >= len) break; + + /* blackman filter. by default, window centered at j+.5(filter_l%2) */ + /* but we want a window centered at time0. */ + offset = ( time0 -gfc->itime[ch] - (j + .5*(filter_l%2))); + assert(fabs(offset)<=.501); + + /* find the closest precomputed window for this offset: */ + joff = floor((offset*2*bpc) + bpc +.5); + + xvalue = 0.; + for (i=0 ; i<=filter_l ; ++i) { + int j2 = i+j-filter_l/2; + int y; + assert(j2= 0); + y = (j2<0) ? inbuf_old[BLACKSIZE+j2] : inbuf[j2]; +#define PRECOMPUTE +#ifdef PRECOMPUTE + xvalue += y*gfc->blackfilt[joff][i]; +#else + xvalue += y*blackman(i-offset,fcn,filter_l); /* very slow! */ +#endif + } + outbuf[k]=xvalue; + } + + + /* k = number of samples added to outbuf */ + /* last k sample used data from [j-filter_l/2,j+filter_l-filter_l/2] */ + + /* how many samples of input data were used: */ + *num_used = Min(len,filter_l+j-filter_l/2); + + /* adjust our input time counter. Incriment by the number of samples used, + * then normalize so that next output sample is at time 0, next + * input buffer is at time itime[ch] */ + gfc->itime[ch] += *num_used - k*gfc->resample_ratio; + + /* save the last BLACKSIZE samples into the inbuf_old buffer */ + if (*num_used >= BLACKSIZE) { + for (i=0;ireport.debugf != NULL ) { + gfc->report.debugf( format, args ); + } else { + (void) vfprintf ( stderr, format, args ); + fflush ( stderr ); /* an debug function should flush immediately */ + } + + va_end ( args ); +} + + +void lame_msgf (const lame_internal_flags *gfc, const char* format, ... ) +{ + va_list args; + + va_start ( args, format ); + + if ( gfc->report.msgf != NULL ) { + gfc->report.msgf( format, args ); + } else { + (void) vfprintf ( stderr, format, args ); + fflush ( stderr ); /* we print to stderr, so me may want to flush */ + } + + va_end ( args ); +} + + +void lame_errorf (const lame_internal_flags *gfc, const char* format, ... ) +{ + va_list args; + + va_start ( args, format ); + + if ( gfc->report.errorf != NULL ) { + gfc->report.errorf( format, args ); + } else { + (void) vfprintf ( stderr, format, args ); + fflush ( stderr ); /* an error function should flush immediately */ + } + + va_end ( args ); +} + + + +/*********************************************************************** + * + * routines to detect CPU specific features like 3DNow, MMX, SIMD + * + * donated by Frank Klemm + * added Robert Hegemann 2000-10-10 + * + ***********************************************************************/ + +int has_i387 ( void ) +{ +#ifdef HAVE_NASM + return 1; +#else + return 0; /* don't know, assume not */ +#endif +} + +int has_MMX ( void ) +{ +#ifdef HAVE_NASM + extern int has_MMX_nasm ( void ); + return has_MMX_nasm (); +#else + return 0; /* don't know, assume not */ +#endif +} + +int has_3DNow ( void ) +{ +#ifdef HAVE_NASM + extern int has_3DNow_nasm ( void ); + return has_3DNow_nasm (); +#else + return 0; /* don't know, assume not */ +#endif +} + +int has_SIMD ( void ) +{ +#ifdef HAVE_NASM + extern int has_SIMD_nasm ( void ); + return has_SIMD_nasm (); +#else + return 0; /* don't know, assume not */ +#endif +} + +int has_SIMD2 ( void ) +{ +#ifdef HAVE_NASM + extern int has_SIMD2_nasm ( void ); + return has_SIMD2_nasm (); +#else + return 0; /* don't know, assume not */ +#endif +} + +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +void updateStats( lame_internal_flags * const gfc ) +{ + assert ( gfc->bitrate_index < 16u ); + assert ( gfc->mode_ext < 4u ); + + /* count bitrate indices */ + gfc->bitrate_stereoMode_Hist [gfc->bitrate_index] [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]++; +} + + + +/* caution: a[] will be resorted!! + */ +int select_kth_int(int a[], int N, int k) +{ + int i, j, l, r, v, w; + + l = 0; + r = N-1; + while (r > l) { + v = a[r]; + i = l-1; + j = r; + for (;;) { + while (a[++i] < v) /*empty*/; + while (a[--j] > v) /*empty*/; + if (i >= j) + break; + /* swap i and j */ + w = a[i]; + a[i] = a[j]; + a[j] = w; + } + /* swap i and r */ + w = a[i]; + a[i] = a[r]; + a[r] = w; + if (i >= k) + r = i-1; + if (i <= k) + l = i+1; + } + return a[k]; +} + + + +void disable_FPE(void) { +/* extremly system dependent stuff, move to a lib to make the code readable */ +/*==========================================================================*/ + + + + /* + * Disable floating point exceptions + */ + + + + +#if defined(__FreeBSD__) && !defined(__alpha__) + { + /* seet floating point mask to the Linux default */ + fp_except_t mask; + mask = fpgetmask(); + /* if bit is set, we get SIGFPE on that error! */ + fpsetmask(mask & ~(FP_X_INV | FP_X_DZ)); + /* DEBUGF("FreeBSD mask is 0x%x\n",mask); */ + } +#endif + +#if defined(__riscos__) && !defined(ABORTFP) + /* Disable FPE's under RISC OS */ + /* if bit is set, we disable trapping that error! */ + /* _FPE_IVO : invalid operation */ + /* _FPE_DVZ : divide by zero */ + /* _FPE_OFL : overflow */ + /* _FPE_UFL : underflow */ + /* _FPE_INX : inexact */ + DisableFPETraps(_FPE_IVO | _FPE_DVZ | _FPE_OFL); +#endif + + /* + * Debugging stuff + * The default is to ignore FPE's, unless compiled with -DABORTFP + * so add code below to ENABLE FPE's. + */ + +#if defined(ABORTFP) +#if defined(_MSC_VER) + { + + /* set affinity to a single CPU. Fix for EAC/lame on SMP systems from + "Todd Richmond" */ + SYSTEM_INFO si; + GetSystemInfo(&si); + SetProcessAffinityMask(GetCurrentProcess(), si.dwActiveProcessorMask); + +#include + unsigned int mask; + mask = _controlfp(0, 0); + mask &= ~(_EM_OVERFLOW | _EM_UNDERFLOW | _EM_ZERODIVIDE | _EM_INVALID); + mask = _controlfp(mask, _MCW_EM); + } +#elif defined(__CYGWIN__) +# define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw)) + +# define _EM_INEXACT 0x00000020 /* inexact (precision) */ +# define _EM_UNDERFLOW 0x00000010 /* underflow */ +# define _EM_OVERFLOW 0x00000008 /* overflow */ +# define _EM_ZERODIVIDE 0x00000004 /* zero divide */ +# define _EM_INVALID 0x00000001 /* invalid */ + { + unsigned int mask; + _FPU_GETCW(mask); + /* Set the FPU control word to abort on most FPEs */ + mask &= ~(_EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID); + _FPU_SETCW(mask); + } +# elif defined(__linux__) + { + +# include +# ifndef _FPU_GETCW +# define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw)) +# endif +# ifndef _FPU_SETCW +# define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw)) +# endif + + /* + * Set the Linux mask to abort on most FPE's + * if bit is set, we _mask_ SIGFPE on that error! + * mask &= ~( _FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM ); + */ + + unsigned int mask; + _FPU_GETCW(mask); + mask &= ~(_FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM); + _FPU_SETCW(mask); + } +#endif +#endif /* ABORTFP */ +} + + +/* end of util.c */ diff --git a/lib/lame/util.h b/lib/lame/util.h new file mode 100644 index 0000000..a042409 --- /dev/null +++ b/lib/lame/util.h @@ -0,0 +1,615 @@ +/* + * lame utility library include file + * + * Copyright (c) 1999 Albert L Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_UTIL_H +#define LAME_UTIL_H + +/*********************************************************************** +* +* Global Include Files +* +***********************************************************************/ +#include "machine.h" +#include "encoder.h" +#include "lame.h" +#include "lame_global_flags.h" +#include "lame-analysis.h" +#include "id3tag.h" + +/*********************************************************************** +* +* Global Definitions +* +***********************************************************************/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#ifdef UINT_MAX +# define MAX_U_32_NUM UINT_MAX +#else +# define MAX_U_32_NUM 0xFFFFFFFF +#endif + +#ifndef PI +# ifdef M_PI +# define PI M_PI +# else +# define PI 3.14159265358979323846 +# endif +#endif + + +#ifdef M_LN2 +# define LOG2 M_LN2 +#else +# define LOG2 0.69314718055994530942 +#endif + +#ifdef M_LN10 +# define LOG10 M_LN10 +#else +# define LOG10 2.30258509299404568402 +#endif + + +#ifdef M_SQRT2 +# define SQRT2 M_SQRT2 +#else +# define SQRT2 1.41421356237309504880 +#endif + + +#define HAN_SIZE 512 +#define CRC16_POLYNOMIAL 0x8005 +#define MAX_BITS 4095 + +/* "bit_stream.h" Definitions */ +#define BUFFER_SIZE LAME_MAXMP3BUFFER + +#define Min(A, B) ((A) < (B) ? (A) : (B)) +#define Max(A, B) ((A) > (B) ? (A) : (B)) + + + + + +/*********************************************************************** +* +* Global Type Definitions +* +***********************************************************************/ + + + +/* "bit_stream.h" Type Definitions */ + +typedef struct bit_stream_struc { + unsigned char *buf; /* bit stream buffer */ + int buf_size; /* size of buffer (in number of bytes) */ + int totbit; /* bit counter of bit stream */ + int buf_byte_idx; /* pointer to top byte in buffer */ + int buf_bit_idx; /* pointer to top bit of top byte in buffer */ + + /* format of file in rd mode (BINARY/ASCII) */ +} Bit_stream_struc; + +#include "l3side.h" + + +/* variables used for --nspsytune */ +typedef struct { + int use; /* indicates the use of exp_nspsytune */ + int safejoint; /* safe joint stereo mode */ + FLOAT last_en_subshort[4][9]; + FLOAT last_attack_intensity[4][9]; + FLOAT last_thm[4][SBMAX_s][3]; + int last_attacks[4][3]; + FLOAT pe_l[4],pe_s[4]; + FLOAT pefirbuf[19]; + FLOAT bass,alto,treble,sfb21; +} nsPsy_t; + +/* variables used for --alt-preset */ +typedef struct { + + // indicates the use of alt-preset + int use; + + // short block tuning + int attackthre; + int attackthre_s; + + // adjustment to joint stereo + FLOAT8 ms_maskadjust; + + // adjustments to quantization selection + int quantcomp_current; // current quant_compare mode we are using + FLOAT8 quantcomp_adjust_rh_tot; // adjustments for tot_noise with vbr-old + FLOAT8 quantcomp_adjust_rh_max; // adjustments for max_noise with vbr-old + FLOAT8 quantcomp_adjust_mtrh; // adjustments for calc_scalefac "c" with vbr-mtrh + int quantcomp_type_s; // quantization comparison to switch to on non-normal blocks + int quantcomp_alt_type; // third quantization comparison to use for special cases + // such as high athadjust values, or long blocks, etc + + // tunings reliant upon athadjust + FLOAT8 athadjust_max_val; // maximum value of athadjust before limit is applied + FLOAT8 athadjust_switch_level; // level of athadjust at which to apply tunings at + // x <= 0 == never switch, x >= 1 == always switch + FLOAT8 athadjust_msfix; // msfix adjustment based on athadjust + int athadjust_safe_noiseshaping; // if 0, noise shaping 2 will not be used no matter what + // the noise shaping type would normally be set to + FLOAT8 athadjust_safe_noiseshaping_thre; // value which max_pow_alt must be greater than + // for noise shaping 2 to be used "safely" + FLOAT8 athadjust_safe_athaasensitivity; // used for second determination if it is safe to switch + // to noise shaping 2 +} presetTune_t; + +typedef struct +{ + int sum; // what we have seen so far + int seen; // how many frames we have seen in this chunk + int want; // how many frames we want to collect into one chunk + int pos; // actual position in our bag + int size; // size of our bag + int *bag; // pointer to our bag +} VBR_seek_info_t; + + +/** + * ATH related stuff, if something new ATH related has to be added, + * please plugg it here into the ATH_t struct + */ +typedef struct +{ + int use_adjust; // method for the auto adjustment + FLOAT8 adjust; // lowering based on peak volume, 1 = no lowering + FLOAT8 adjust_limit; // limit for dynamic ATH adjust + FLOAT8 decay; // determined to lower x dB each second + FLOAT8 floor; // lowest ATH value + FLOAT8 l[SBMAX_l]; // ATH for sfbs in long blocks + FLOAT8 s[SBMAX_s]; // ATH for sfbs in short blocks + FLOAT8 cb[CBANDS]; // ATH for convolution bands +} ATH_t; + +/** + * VBR related stuff + */ +typedef struct +{ + int quality; + FLOAT8 mask_adjust; // the dbQ stuff + int smooth; // 0=no, 1=peaks, 2=+-4 + int bitpressure; // strategy for bitpressure situations + FLOAT8 scratch[192]; +} VBR_t; + +/** + * PSY Model related stuff + */ +typedef struct +{ + int tonalityPatch; // temporaly needed by VBR + FLOAT cwlimit; + FLOAT8 prvTonRed[CBANDS]; +} PSY_t; + + +/* Guest structure, only temporarly here */ + +typedef enum { + coding_MPEG_Layer_1 = 1, + coding_MPEG_Layer_2 = 2, + coding_MPEG_Layer_3 = 3, + coding_MPEG_AAC = 4, + coding_Ogg_Vorbis = 5, + coding_MPEG_plus = 6 +} coding_t; + +#define MAX_CHANNELS 2 + +typedef struct { + unsigned long Class_ID; /* Class ID to recognize a resample_t + object */ + FLOAT8 sample_freq_in; /* Input sample frequency in Hz */ + FLOAT8 sample_freq_out; /* requested Output sample frequency in Hz */ + FLOAT8 lowpass_freq; /* lowpass frequency, this is the -6 dB + point */ + int scale_in; /* the resampling is actually done by + scale_out: */ + int scale_out; /* frequency is + samplefreq_in * scale_out / scal */ + int taps; /* number of taps for every FIR resample + filter */ + + sample_t** fir; /* the FIR resample filters: + fir [scale_out] [taps */ + void* firfree; /* start address of the alloced memory for + fir, */ + unsigned char* src_step; + sample_t* in_old [MAX_CHANNELS]; + // uint64_t sample_count [MAX_CHANNELS]; + unsigned fir_stepper [MAX_CHANNELS]; + int inp_stepper [MAX_CHANNELS]; + +} resample_t; + + +struct lame_internal_flags { + + /******************************************************************** + * internal variables NOT set by calling program, and should not be * + * modified by the calling program * + ********************************************************************/ + + /* + * Some remarks to the Class_ID field: + * The Class ID is an Identifier for a pointer to this struct. + * It is very unlikely that a pointer to lame_global_flags has the same 32 bits + * in it's structure (large and other special properties, for instance prime). + * + * To test that the structure is right and initialized, use: + * if ( gfc -> Class_ID == LAME_ID ) ... + * Other remark: + * If you set a flag to 0 for uninit data and 1 for init data, the right test + * should be "if (flag == 1)" and NOT "if (flag)". Unintended modification + * of this element will be otherwise misinterpreted as an init. + */ + + #define LAME_ID 0xFFF88E3B + unsigned long Class_ID; + + struct { + void (*msgf) (const char *format, va_list ap); + void (*debugf)(const char *format, va_list ap); + void (*errorf)(const char *format, va_list ap); + } report; + + int lame_encode_frame_init; + int iteration_init_init; + int fill_buffer_resample_init; + int psymodel_init; + + int padding; /* padding for the current frame? */ + int mode_gr; /* granules per frame */ + int channels_in; /* number of channels in the input data stream (PCM or decoded PCM) */ + int channels_out; /* number of channels in the output data stream (not used for decoding) */ + resample_t* resample_in; /* context for coding (PCM=>MP3) resampling */ + resample_t* resample_out; /* context for decoding (MP3=>PCM) resampling */ + FLOAT8 samplefreq_in; + FLOAT8 samplefreq_out; + uint16_t nMusicCRC; + +#ifndef MFSIZE +# define MFSIZE ( 3*1152 + ENCDELAY - MDCTDELAY ) +#endif +#ifdef KLEMM_44 + sample_t* mfbuf [MAX_CHANNELS]; +#else + sample_t mfbuf [2] [MFSIZE]; +#endif + size_t frame_size; /* size of one frame in samples per channel */ + lame_global_flags* gfp; /* needed as long as the frame encoding functions must access gfp (all needed information can be added to gfc) */ + coding_t coding; /* MPEG Layer 1/2/3, Ogg Vorbis, MPEG AAC, ... */ + unsigned long frame_count; /* Number of frames coded, 2^32 > 3 years */ + int mf_samples_to_encode; + int mf_size; + FLOAT8 ampl; /* amplification at the end of the current chunk (1. = 0 dB) */ + FLOAT8 last_ampl; /* amplification at the end of the last chunk (1. = 0 dB) */ + int VBR_min_bitrate; /* min bitrate index */ + int VBR_max_bitrate; /* max bitrate index */ + FLOAT resample_ratio; /* input_samp_rate/output_samp_rate */ + int bitrate_index; + int samplerate_index; + int mode_ext; + + + /* lowpass and highpass filter control */ + FLOAT8 lowpass1,lowpass2; /* normalized frequency bounds of passband */ + FLOAT8 highpass1,highpass2; /* normalized frequency bounds of passband */ + + /* polyphase filter (filter_type=0) */ + int lowpass_band; /* zero bands >= lowpass_band in the polyphase filterbank */ + int highpass_band; /* zero bands <= highpass_band */ + int lowpass_start_band; /* amplify bands between start */ + int lowpass_end_band; /* and end for lowpass */ + int highpass_start_band; /* amplify bands between start */ + int highpass_end_band; /* and end for highpass */ + + + int filter_type; /* 0=polyphase filter, 1= FIR filter 2=MDCT filter(bad)*/ + int quantization; /* 0 = ISO formual, 1=best amplitude */ + int noise_shaping; /* 0 = none + 1 = ISO AAC model + 2 = allow scalefac_select=1 + */ + + int noise_shaping_amp; /* 0 = ISO model: amplify all distorted bands + 1 = amplify within 50% of max (on db scale) + 2 = amplify only most distorted band + 3 = amplify only most distorted band and + use pseudo half step + */ + + int psymodel; /* 1 = gpsycho. 0 = none */ + int noise_shaping_stop; /* 0 = stop at over=0, all scalefacs amplified or + a scalefac has reached max value + 1 = stop when all scalefacs amplified or + a scalefac has reached max value + 2 = stop when all scalefacs amplified + */ + + int use_best_huffman; /* 0 = no. 1=outside loop 2=inside loop(slow) */ + + + + + /* variables used by lame.c */ + Bit_stream_struc bs; + III_side_info_t l3_side; + FLOAT8 ms_ratio[2]; + /* used for padding */ + int frac_SpF; + int slot_lag; + + + /* optional ID3 tags, used in id3tag.c */ + struct id3tag_spec tag_spec; + + + /* variables used by quantize.c */ + int OldValue[2]; + int CurrentStep; + FLOAT8 decay; + FLOAT8 masking_lower; + + char bv_scf[576]; + + int sfb21_extra; /* will be set in lame_init_params */ + + int is_mpeg1; /* 1 for MPEG-1, 0 for MPEG-2(.5) */ + +#ifndef KLEMM_44 + /* variables used by util.c */ + /* BPC = maximum number of filter convolution windows to precompute */ +#define BPC 320 + sample_t *inbuf_old [2]; + sample_t *blackfilt [2*BPC+1]; + FLOAT8 itime[2]; +#endif + int sideinfo_len; + + /* variables for newmdct.c */ + FLOAT8 sb_sample[2][2][18][SBLIMIT]; + FLOAT8 amp_lowpass[32]; + FLOAT8 amp_highpass[32]; + + /* variables for bitstream.c */ + /* mpeg1: buffer=511 bytes smallest frame: 96-38(sideinfo)=58 + * max number of frames in reservoir: 8 + * mpeg2: buffer=255 bytes. smallest frame: 24-23bytes=1 + * with VBR, if you are encoding all silence, it is possible to + * have 8kbs/24khz frames with 1byte of data each, which means we need + * to buffer up to 255 headers! */ + /* also, max_header_buf has to be a power of two */ +#define MAX_HEADER_BUF 256 +#define MAX_HEADER_LEN 40 /* max size of header is 38 */ + struct { + int write_timing; + int ptr; + char buf[MAX_HEADER_LEN]; + } header[MAX_HEADER_BUF]; + + int h_ptr; + int w_ptr; + int ancillary_flag; + + + /* variables for reservoir.c */ + int ResvSize; /* in bits */ + int ResvMax; /* in bits */ + + + scalefac_struct scalefac_band; + + /* DATA FROM PSYMODEL.C */ +/* The static variables "r", "phi_sav", "new", "old" and "oldest" have */ +/* to be remembered for the unpredictability measure. For "r" and */ +/* "phi_sav", the first index from the left is the channel select and */ +/* the second index is the "age" of the data. */ + FLOAT8 minval[CBANDS]; + FLOAT8 nb_1[4][CBANDS], nb_2[4][CBANDS]; + FLOAT8 nb_s1[4][CBANDS], nb_s2[4][CBANDS]; + FLOAT8 *s3_ss; + FLOAT8 *s3_ll; + + III_psy_xmin thm[4]; + III_psy_xmin en[4]; + + /* unpredictability calculation + */ + int cw_upper_index; + int cw_lower_index; + FLOAT ax_sav[4][2][HBLKSIZE]; + FLOAT bx_sav[4][2][HBLKSIZE]; + FLOAT rx_sav[4][2][HBLKSIZE]; + FLOAT cw[HBLKSIZE]; + + /* fft and energy calculation */ + FLOAT wsamp_L[2][BLKSIZE]; + FLOAT energy[HBLKSIZE]; + FLOAT wsamp_S[2][3][BLKSIZE_s]; + FLOAT energy_s[3][HBLKSIZE_s]; + FLOAT tot_ener[4]; + + + /* loudness calculation (for adaptive threshold of hearing) */ + FLOAT loudness_sq[2][2]; /* loudness^2 approx. per granule and channel */ + FLOAT loudness_sq_save[2];/* account for granule delay of L3psycho_anal */ + + /* factor for tuning the (sample power) point below which adaptive threshold + of hearing adjustment occurs + */ + FLOAT athaa_sensitivity_p; + + + /* fft.c */ + FLOAT window[BLKSIZE], window_s[BLKSIZE_s/2]; + + + /* Scale Factor Bands */ + III_scalefac_t pseudohalf; + FLOAT8 w1_l[SBMAX_l], w2_l[SBMAX_l]; + FLOAT8 w1_s[SBMAX_s], w2_s[SBMAX_s]; + FLOAT8 mld_l[SBMAX_l],mld_s[SBMAX_s]; + int bu_l[SBMAX_l],bo_l[SBMAX_l] ; + int bu_s[SBMAX_s],bo_s[SBMAX_s] ; + int npart_l,npart_s; + int npart_l_orig,npart_s_orig; + + int s3ind[CBANDS][2]; + int s3ind_s[CBANDS][2]; + FLOAT8 SNR_s[CBANDS]; + + int numlines_s[CBANDS]; + int numlines_l[CBANDS]; + + + /* frame analyzer */ + FLOAT energy_save[4][HBLKSIZE]; + FLOAT8 pe_save[4]; + FLOAT8 ers_save[4]; + + /* simple statistics */ + int bitrate_stereoMode_Hist [16] [4+1]; + + /* ratios */ + FLOAT8 pe[4]; + FLOAT8 ms_ratio_s_old,ms_ratio_l_old; + FLOAT8 ms_ener_ratio_old; + + /* block type */ + int blocktype_old[2]; + + /* used by the frame analyzer */ + plotting_data *pinfo; + + /* CPU features */ + struct { + unsigned int i387 : 1; /* FPU is a normal Intel CPU */ + unsigned int MMX : 1; /* Pentium MMX, Pentium II...IV, K6, K6-2, + K6-III, Athlon */ + unsigned int AMD_3DNow : 1; /* K6-2, K6-III, Athlon */ + unsigned int SIMD : 1; /* Pentium III, Pentium 4 */ + unsigned int SIMD2 : 1; /* Pentium 4, K8 */ + } CPU_features; + + /* functions to replace with CPU feature optimized versions in takehiro.c */ + int (*choose_table)(const int *ix, const int *end, int *s); + + void (*fft_fht)(FLOAT *, int); + + nsPsy_t nsPsy; /* variables used for --nspsytune */ + presetTune_t presetTune; /* variables used for --alt-preset */ + + unsigned crcvalue; + + VBR_seek_info_t VBR_seek_table; // used for Xing VBR header + + ATH_t *ATH; // all ATH related stuff + VBR_t *VBR; + PSY_t *PSY; + + int nogap_total; + int nogap_current; +}; + + + + + +/*********************************************************************** +* +* Global Function Prototype Declarations +* +***********************************************************************/ +void freegfc(lame_internal_flags * const gfc); +extern int BitrateIndex(int, int,int); +extern int FindNearestBitrate(int,int,int); +extern int map2MP3Frequency(int freq); +extern int SmpFrqIndex(int, int* const); +extern FLOAT8 ATHformula(FLOAT8 f,lame_global_flags *gfp); +extern FLOAT8 freq2bark(FLOAT8 freq); +extern FLOAT8 freq2cbw(FLOAT8 freq); +extern void freorder(int scalefac_band[],FLOAT8 ix_orig[576]); +void disable_FPE(void); + +extern void +getframebits( const lame_global_flags *gfp, int *bitsPerFrame, int *mean_bits); + +void fill_buffer(lame_global_flags *gfp, + sample_t *mfbuf[2], + sample_t *in_buffer[2], + int nsamples, int *n_in, int *n_out); + +int fill_buffer_resample ( + lame_global_flags *gfp, + sample_t* outbuf, + int desired_len, + sample_t* inbuf, + int len, + int* num_used, + int channels ); + + +extern int has_i387 ( void ); +extern int has_MMX ( void ); +extern int has_3DNow ( void ); +extern int has_SIMD ( void ); +extern int has_SIMD2 ( void ); + +extern void updateStats (lame_internal_flags * const gfc); + + + +/*********************************************************************** +* +* Macros about Message Printing and Exit +* +***********************************************************************/ +extern void lame_errorf(const lame_internal_flags *gfc, const char *, ...); +extern void lame_debugf(const lame_internal_flags *gfc, const char *, ...); +extern void lame_msgf (const lame_internal_flags *gfc, const char *, ...); +#define DEBUGF lame_debugf +#define ERRORF lame_errorf +#define MSGF lame_msgf + + +int select_kth_int(int b[], int N, int k); + + + +#endif /* LAME_UTIL_H */ diff --git a/lib/lame/vbrquantize.c b/lib/lame/vbrquantize.c new file mode 100644 index 0000000..8d96ab8 --- /dev/null +++ b/lib/lame/vbrquantize.c @@ -0,0 +1,1769 @@ +/* + * MP3 quantization + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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: vbrquantize.c,v 1.1 2002/04/28 17:30:30 kramm Exp $ */ + +#include "config_static.h" + +#include +#include "util.h" +#include "l3side.h" +#include "reservoir.h" +#include "quantize_pvt.h" +#include "vbrquantize.h" + +#ifdef WITH_DMALLOC +#include +#endif + + + +typedef union { + float f; + int i; +} fi_union; + +#define MAGIC_FLOAT (65536*(128)) +#define MAGIC_INT 0x4b000000 + +#ifdef TAKEHIRO_IEEE754_HACK + +#define DUFFBLOCKMQ() do { \ + xp = xr34[0] * sfpow34_p1; \ + xe = xr34[0] * sfpow34_eq; \ + xm = xr34[0] * sfpow34_m1; \ + if (xm > IXMAX_VAL) \ + return -1; \ + xp += MAGIC_FLOAT; \ + xe += MAGIC_FLOAT; \ + xm += MAGIC_FLOAT; \ + fi[0].f = xp; \ + fi[1].f = xe; \ + fi[2].f = xm; \ + fi[0].f = xp + (adj43asm - MAGIC_INT)[fi[0].i]; \ + fi[1].f = xe + (adj43asm - MAGIC_INT)[fi[1].i]; \ + fi[2].f = xm + (adj43asm - MAGIC_INT)[fi[2].i]; \ + fi[0].i -= MAGIC_INT; \ + fi[1].i -= MAGIC_INT; \ + fi[2].i -= MAGIC_INT; \ + x0 = fabs(xr[0]); \ + xp = x0 - pow43[fi[0].i] * sfpow_p1; \ + xe = x0 - pow43[fi[1].i] * sfpow_eq; \ + xm = x0 - pow43[fi[2].i] * sfpow_m1; \ + xp *= xp; \ + xe *= xe; \ + xm *= xm; \ + xfsf_eq = Max(xfsf_eq, xe); \ + xfsf_p1 = Max(xfsf_p1, xp); \ + xfsf_m1 = Max(xfsf_m1, xm); \ + ++xr; \ + ++xr34; \ + } while(0) + +#define DUFFBLOCK() do { \ + xp = xr34[0] * sfpow34_p1; \ + xe = xr34[0] * sfpow34_eq; \ + xm = xr34[0] * sfpow34_m1; \ + if (xm > IXMAX_VAL) \ + return -1; \ + xp += MAGIC_FLOAT; \ + xe += MAGIC_FLOAT; \ + xm += MAGIC_FLOAT; \ + fi[0].f = xp; \ + fi[1].f = xe; \ + fi[2].f = xm; \ + fi[0].f = xp + (adj43asm - MAGIC_INT)[fi[0].i]; \ + fi[1].f = xe + (adj43asm - MAGIC_INT)[fi[1].i]; \ + fi[2].f = xm + (adj43asm - MAGIC_INT)[fi[2].i]; \ + fi[0].i -= MAGIC_INT; \ + fi[1].i -= MAGIC_INT; \ + fi[2].i -= MAGIC_INT; \ + x0 = fabs(xr[0]); \ + xp = x0 - pow43[fi[0].i] * sfpow_p1; \ + xe = x0 - pow43[fi[1].i] * sfpow_eq; \ + xm = x0 - pow43[fi[2].i] * sfpow_m1; \ + xfsf_p1 += xp * xp; \ + xfsf_eq += xe * xe; \ + xfsf_m1 += xm * xm; \ + ++xr; \ + ++xr34; \ + } while(0) + +#else + +/********************************************************************* + * XRPOW_FTOI is a macro to convert floats to ints. + * if XRPOW_FTOI(x) = nearest_int(x), then QUANTFAC(x)=adj43asm[x] + * ROUNDFAC= -0.0946 + * + * if XRPOW_FTOI(x) = floor(x), then QUANTFAC(x)=asj43[x] + * ROUNDFAC=0.4054 + *********************************************************************/ +# define QUANTFAC(rx) adj43[rx] +# define ROUNDFAC 0.4054 +# define XRPOW_FTOI(src,dest) ((dest) = (int)(src)) + + +#endif + +/* caution: a[] will be resorted!! + */ +FLOAT8 select_kth(FLOAT8 a[], int N, int k) +{ + int i, j, l, r; + FLOAT8 v, w; + + l = 0; + r = N-1; + while (r > l) { + v = a[r]; + i = l-1; + j = r; + for (;;) { + while (a[++i] < v) /*empty*/; + while (a[--j] > v) /*empty*/; + if (i >= j) + break; + /* swap i and j */ + w = a[i]; + a[i] = a[j]; + a[j] = w; + } + /* swap i and r */ + w = a[i]; + a[i] = a[r]; + a[r] = w; + if (i >= k) + r = i-1; + if (i <= k) + l = i+1; + } + return a[k]; +} + + + + +static FLOAT8 +calc_sfb_noise(const FLOAT8 *xr, const FLOAT8 *xr34, int bw, int sf) +{ + int j; + fi_union fi; + FLOAT8 temp; + FLOAT8 xfsf = 0; + FLOAT8 sfpow, sfpow34; + + sfpow = POW20(sf+210); /*pow(2.0,sf/4.0); */ + sfpow34 = IPOW20(sf+210); /*pow(sfpow,-3.0/4.0);*/ + + for ( j = 0; j < bw ; ++j ) { + if ( xr34[j]*sfpow34 > IXMAX_VAL ) return -1; + +#ifdef TAKEHIRO_IEEE754_HACK + temp = sfpow34*xr34[j]; + temp += MAGIC_FLOAT; + fi.f = temp; + fi.f = temp + (adj43asm - MAGIC_INT)[fi.i]; + fi.i -= MAGIC_INT; +#else + temp = xr34[j]*sfpow34; + XRPOW_FTOI(temp, fi.i); + XRPOW_FTOI(temp + QUANTFAC(fi.i), fi.i); +#endif + + temp = fabs(xr[j])- pow43[fi.i]*sfpow; + xfsf += temp*temp; + } + return xfsf; +} + + + + +static FLOAT8 +calc_sfb_noise_mq( const FLOAT8 *xr, const FLOAT8 *xr34, int bw, int sf, + int mq, FLOAT8 *scratch ) +{ + int j, k; + fi_union fi; + FLOAT8 temp; + FLOAT8 sfpow, sfpow34, xfsfm = 0, xfsf = 0; + + sfpow = POW20(sf+210); /*pow(2.0,sf/4.0); */ + sfpow34 = IPOW20(sf+210); /*pow(sfpow,-3.0/4.0);*/ + + for ( j = 0; j < bw; ++j ) { + if ( xr34[j]*sfpow34 > IXMAX_VAL ) return -1; + +#ifdef TAKEHIRO_IEEE754_HACK + temp = sfpow34*xr34[j]; + temp += MAGIC_FLOAT; + fi.f = temp; + fi.f = temp + (adj43asm - MAGIC_INT)[fi.i]; + fi.i -= MAGIC_INT; +#else + temp = xr34[j]*sfpow34; + XRPOW_FTOI(temp, fi.i); + XRPOW_FTOI(temp + QUANTFAC(fi.i), fi.i); +#endif + + temp = fabs(xr[j])- pow43[fi.i]*sfpow; + temp *= temp; + + scratch[j] = temp; + if ( xfsfm < temp ) xfsfm = temp; + xfsf += temp; + } + if ( mq == 1 ) return bw*select_kth(scratch,bw,bw*13/16); + + xfsf /= bw; + for ( k = 1, j = 0; j < bw; ++j ) { + if ( scratch[j] > xfsf ) { + xfsfm += scratch[j]; + ++k; + } + } + return xfsfm/k * bw; +} + + + + +static FLOAT8 +calc_sfb_noise_ave(const FLOAT8 *xr, const FLOAT8 *xr34, int bw, int sf) +{ + double xp; + double xe; + double xm; +#ifdef TAKEHIRO_IEEE754_HACK + double x0; +#endif + int xx[3], j; + fi_union *fi = (fi_union *)xx; + FLOAT8 sfpow34_eq, sfpow34_p1, sfpow34_m1; + FLOAT8 sfpow_eq, sfpow_p1, sfpow_m1; + FLOAT8 xfsf_eq = 0, xfsf_p1 = 0, xfsf_m1 = 0; + + sfpow_eq = POW20(sf + 210); /*pow(2.0,sf/4.0); */ + sfpow_m1 = sfpow_eq * .8408964153; /* pow(2,(sf-1)/4.0) */ + sfpow_p1 = sfpow_eq * 1.189207115; + + sfpow34_eq = IPOW20(sf + 210); /*pow(sfpow,-3.0/4.0);*/ + sfpow34_m1 = sfpow34_eq * 1.13878863476; /* .84089 ^ -3/4 */ + sfpow34_p1 = sfpow34_eq * 0.878126080187; + +#ifdef TAKEHIRO_IEEE754_HACK + /* + * loop unrolled into "Duff's Device". Robert Hegemann + */ + j = (bw+3) / 4; + switch (bw % 4) { + default: + case 0: do{ DUFFBLOCK(); + case 3: DUFFBLOCK(); + case 2: DUFFBLOCK(); + case 1: DUFFBLOCK(); } while (--j); + } +#else + for (j = 0; j < bw; ++j) { + + if (xr34[j]*sfpow34_m1 > IXMAX_VAL) return -1; + + xe = xr34[j]*sfpow34_eq; + XRPOW_FTOI(xe, fi[0].i); + XRPOW_FTOI(xe + QUANTFAC(fi[0].i), fi[0].i); + xe = fabs(xr[j])- pow43[fi[0].i]*sfpow_eq; + xe *= xe; + + xp = xr34[j]*sfpow34_p1; + XRPOW_FTOI(xp, fi[0].i); + XRPOW_FTOI(xp + QUANTFAC(fi[0].i), fi[0].i); + xp = fabs(xr[j])- pow43[fi[0].i]*sfpow_p1; + xp *= xp; + + xm = xr34[j]*sfpow34_m1; + XRPOW_FTOI(xm, fi[0].i); + XRPOW_FTOI(xm + QUANTFAC(fi[0].i), fi[0].i); + xm = fabs(xr[j])- pow43[fi[0].i]*sfpow_m1; + xm *= xm; + + xfsf_eq += xe; + xfsf_p1 += xp; + xfsf_m1 += xm; + } +#endif + + if ( xfsf_eq < xfsf_p1 ) xfsf_eq = xfsf_p1; + if ( xfsf_eq < xfsf_m1 ) xfsf_eq = xfsf_m1; + return xfsf_eq; +} + + + +INLINE int +find_scalefac( const FLOAT8 *xr, const FLOAT8 *xr34, FLOAT8 l3_xmin, int bw ) +{ + FLOAT8 xfsf; + int i, sf, sf_ok, delsf; + + /* search will range from sf: -209 -> 45 */ + sf = -82; + delsf = 128; + + sf_ok = 10000; + for (i = 0; i < 7; ++i) { + delsf /= 2; + xfsf = calc_sfb_noise( xr, xr34, bw, sf ); + + if (xfsf < 0) { + /* scalefactors too small */ + sf += delsf; + } + else { + if (xfsf > l3_xmin) { + /* distortion. try a smaller scalefactor */ + sf -= delsf; + } + else { + sf_ok = sf; + sf += delsf; + } + } + } + + /* returning a scalefac without distortion, if possible + */ + return sf_ok > 45 ? sf : sf_ok; +} + +INLINE int +find_scalefac_mq( const FLOAT8 *xr, const FLOAT8 *xr34, FLOAT8 l3_xmin, + int bw, int mq, FLOAT8 *scratch ) +{ + FLOAT8 xfsf; + int i, sf, sf_ok, delsf; + + /* search will range from sf: -209 -> 45 */ + sf = -82; + delsf = 128; + + sf_ok = 10000; + for (i = 0; i < 7; ++i) { + delsf /= 2; + xfsf = calc_sfb_noise_mq( xr, xr34, bw, sf, mq, scratch ); + + if (xfsf < 0) { + /* scalefactors too small */ + sf += delsf; + } + else { + if (xfsf > l3_xmin) { + /* distortion. try a smaller scalefactor */ + sf -= delsf; + } + else { + sf_ok = sf; + sf += delsf; + } + } + } + + /* returning a scalefac without distortion, if possible + */ + return sf_ok > 45 ? sf : sf_ok; +} + +INLINE int +find_scalefac_ave( const FLOAT8 *xr, const FLOAT8 *xr34, FLOAT8 l3_xmin, int bw ) +{ + FLOAT8 xfsf; + int i, sf, sf_ok, delsf; + + /* search will range from sf: -209 -> 45 */ + sf = -82; + delsf = 128; + + sf_ok = 10000; + for (i = 0; i < 7; ++i) { + delsf /= 2; + xfsf = calc_sfb_noise_ave( xr, xr34, bw, sf ); + + if (xfsf < 0) { + /* scalefactors too small */ + sf += delsf; + } + else{ + if (xfsf > l3_xmin) { + /* distortion. try a smaller scalefactor */ + sf -= delsf; + } + else { + sf_ok = sf; + sf += delsf; + } + } + } + + /* returning a scalefac without distortion, if possible + */ + return sf_ok > 45 ? sf : sf_ok; +} + + +/** + * Robert Hegemann 2001-05-01 + * calculates quantization step size determined by allowed masking + */ +INLINE int +calc_scalefac( FLOAT8 l3_xmin, int bw, FLOAT8 preset_tune ) +{ + FLOAT8 const c = (preset_tune > 0 ? preset_tune + : 5.799142446); // 10 * 10^(2/3) * log10(4/3) + return (int)(c*log10(l3_xmin/bw)-.5); +} + + + +static const int max_range_short[SBMAX_s] = +{15, 15, 15, 15, 15, 15, 7, 7, 7, 7, 7, 7, 0 }; + +static const int max_range_long[SBMAX_l] = +{15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0}; + +static const int max_range_long_lsf_pretab[SBMAX_l] = +{ 7,7,7,7,7,7, 3,3,3,3,3, 0,0,0,0, 0,0,0, 0,0,0, 0 }; + + + +/* + sfb=0..5 scalefac < 16 + sfb>5 scalefac < 8 + + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + ol_sf = (cod_info->global_gain-210.0); + ol_sf -= 8*cod_info->subblock_gain[i]; + ol_sf -= ifqstep*scalefac[gr][ch].s[sfb][i]; + +*/ +INLINE int +compute_scalefacs_short( + int sf[][3], const gr_info *cod_info, int scalefac[][3], int *sbg ) +{ + const int maxrange1 = 15, maxrange2 = 7; + int maxrange, maxover = 0; + int sfb, i; + int ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + + for (i = 0; i < 3; ++i) { + int maxsf1 = 0, maxsf2 = 0, minsf = 1000; + /* see if we should use subblock gain */ + for (sfb = 0; sfb < 6; ++sfb) { /* part 1 */ + if (maxsf1 < -sf[sfb][i]) maxsf1 = -sf[sfb][i]; + if (minsf > -sf[sfb][i]) minsf = -sf[sfb][i]; + } + for (; sfb < SBPSY_s; ++sfb) { /* part 2 */ + if (maxsf2 < -sf[sfb][i]) maxsf2 = -sf[sfb][i]; + if (minsf > -sf[sfb][i]) minsf = -sf[sfb][i]; + } + + /* boost subblock gain as little as possible so we can + * reach maxsf1 with scalefactors + * 8*sbg >= maxsf1 + */ + maxsf1 = Max (maxsf1-maxrange1*ifqstep, maxsf2-maxrange2*ifqstep); + sbg[i] = 0; + if (minsf > 0) sbg[i] = floor (.125*minsf + .001); + if (maxsf1 > 0) sbg[i] = Max (sbg[i], (maxsf1/8 + (maxsf1 % 8 != 0))); + if (sbg[i] > 7) sbg[i] = 7; + + for (sfb = 0; sfb < SBPSY_s; ++sfb) { + sf[sfb][i] += 8*sbg[i]; + + if (sf[sfb][i] < 0) { + maxrange = sfb < 6 ? maxrange1 : maxrange2; + + scalefac[sfb][i] + = -sf[sfb][i]/ifqstep + (-sf[sfb][i]%ifqstep != 0); + + if (scalefac[sfb][i] > maxrange) + scalefac[sfb][i] = maxrange; + + if (maxover < -(sf[sfb][i] + scalefac[sfb][i]*ifqstep)) + maxover = -(sf[sfb][i] + scalefac[sfb][i]*ifqstep); + } + } + scalefac[sfb][i] = 0; + } + + return maxover; +} + + + +/* + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + ol_sf = (cod_info->global_gain-210.0); + ol_sf -= ifqstep*scalefac[gr][ch].l[sfb]; + if (cod_info->preflag && sfb>=11) + ol_sf -= ifqstep*pretab[sfb]; +*/ +INLINE int +compute_scalefacs_long_lsf( int *sf, const gr_info * cod_info, int *scalefac ) +{ + const int * max_range = max_range_long; + int ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + int sfb; + int maxover; + + if (cod_info->preflag) { + max_range = max_range_long_lsf_pretab; + for (sfb = 11; sfb < SBPSY_l; ++sfb) + sf[sfb] += pretab[sfb] * ifqstep; + } + + maxover = 0; + for (sfb = 0; sfb < SBPSY_l; ++sfb) { + + if (sf[sfb] < 0) { + /* ifqstep*scalefac >= -sf[sfb], so round UP */ + scalefac[sfb] = -sf[sfb]/ifqstep + (-sf[sfb] % ifqstep != 0); + if (scalefac[sfb] > max_range[sfb]) + scalefac[sfb] = max_range[sfb]; + + /* sf[sfb] should now be positive: */ + if (-(sf[sfb] + scalefac[sfb]*ifqstep) > maxover) { + maxover = -(sf[sfb] + scalefac[sfb]*ifqstep); + } + } + } + scalefac[sfb] = 0; /* sfb21 */ + + return maxover; +} + + + + + +/* + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + ol_sf = (cod_info->global_gain-210.0); + ol_sf -= ifqstep*scalefac[gr][ch].l[sfb]; + if (cod_info->preflag && sfb>=11) + ol_sf -= ifqstep*pretab[sfb]; +*/ +INLINE int +compute_scalefacs_long( int *sf, const gr_info * cod_info, int *scalefac ) +{ + int ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + int sfb; + int maxover; + + if (cod_info->preflag) { + for (sfb = 11; sfb < SBPSY_l; ++sfb) + sf[sfb] += pretab[sfb] * ifqstep; + } + + maxover = 0; + for (sfb = 0; sfb < SBPSY_l; ++sfb) { + + if (sf[sfb] < 0) { + /* ifqstep*scalefac >= -sf[sfb], so round UP */ + scalefac[sfb] = -sf[sfb]/ifqstep + (-sf[sfb] % ifqstep != 0); + if (scalefac[sfb] > max_range_long[sfb]) + scalefac[sfb] = max_range_long[sfb]; + + /* sf[sfb] should now be positive: */ + if (-(sf[sfb] + scalefac[sfb]*ifqstep) > maxover) { + maxover = -(sf[sfb] + scalefac[sfb]*ifqstep); + } + } + } + scalefac[sfb] = 0; /* sfb21 */ + + return maxover; +} + + + + + + + + +/************************************************************************ + * + * quantize and encode with the given scalefacs and global gain + * + * compute scalefactors, l3_enc, and return number of bits needed to encode + * + * + ************************************************************************/ + +static int +VBR_quantize_granule( + lame_internal_flags * gfc, + FLOAT8 * xr34, + int * l3_enc, + III_scalefac_t * scalefac, + int gr, int ch ) +{ + int status; + III_side_info_t * l3_side = & gfc->l3_side; + gr_info * cod_info = & l3_side->gr[gr].ch[ch].tt; + + /* encode scalefacs */ + if ( gfc->is_mpeg1 ) + status = scale_bitcount( scalefac, cod_info ); + else + status = scale_bitcount_lsf( gfc, scalefac, cod_info ); + + if (status != 0) { + return -1; + } + + /* quantize xr34 */ + cod_info->part2_3_length = count_bits(gfc,l3_enc,xr34,cod_info); + if (cod_info->part2_3_length >= LARGE_BITS) return -2; + cod_info->part2_3_length += cod_info->part2_length; + + + if (gfc->use_best_huffman == 1) { + best_huffman_divide(gfc, cod_info, l3_enc); + } + return 0; +} + + + +/*********************************************************************** + * + * calc_short_block_vbr_sf() + * calc_long_block_vbr_sf() + * + * Mark Taylor 2000-??-?? + * Robert Hegemann 2000-10-25 made functions of it + * + ***********************************************************************/ +static const int MAX_SF_DELTA = 4; + +static void +short_block_sf ( + const lame_internal_flags * gfc, + const III_psy_xmin * l3_xmin, + const FLOAT8 * xr34_orig, + const FLOAT8 * xr34, + III_scalefac_t * vbrsf, + int * vbrmin, + int * vbrmax ) +{ + int j, sfb, b; + int vbrmean, vbrmn; + int sf_cache[SBMAX_s]; + int scalefac_criteria; + + if (gfc->presetTune.use) { + /* map experimentalX settings to internal selections */ + static char const map[] = {2,1,0,3,6}; + scalefac_criteria = map[gfc->presetTune.quantcomp_current]; + } + else { + scalefac_criteria = gfc->VBR->quality; + } + + for (j = 0, sfb = 0; sfb < SBMAX_s; ++sfb) { + for (b = 0; b < 3; ++b) { + const int start = gfc->scalefac_band.s[ sfb ]; + const int end = gfc->scalefac_band.s[ sfb+1 ]; + const int width = end - start; + + switch( scalefac_criteria ) { + default: + /* the fastest + */ + vbrsf->s[sfb][b] = calc_scalefac( l3_xmin->s[sfb][b], width, + gfc->presetTune.quantcomp_adjust_mtrh ); + break; + case 5: + case 4: + case 3: + /* the faster and sloppier mode to use at lower quality + */ + vbrsf->s[sfb][b] = find_scalefac (&xr34[j], &xr34_orig[j], + l3_xmin->s[sfb][b], width); + break; + case 2: + /* the slower and better mode to use at higher quality + */ + vbrsf->s[sfb][b] = find_scalefac_ave (&xr34[j], &xr34_orig[j], + l3_xmin->s[sfb][b], width); + break; + case 1: + /* maxnoise mode to use at higher quality + */ + vbrsf->s[sfb][b] = find_scalefac_mq (&xr34[j], &xr34_orig[j], + l3_xmin->s[sfb][b], width, + 1, gfc->VBR->scratch); + break; + case 0: + /* maxnoise mode to use at higher quality + */ + vbrsf->s[sfb][b] = find_scalefac_mq (&xr34[j], &xr34_orig[j], + l3_xmin->s[sfb][b], width, + 0, gfc->VBR->scratch); + break; + } + j += width; + } + } + + *vbrmax = -10000; + *vbrmin = +10000; + + for (b = 0; b < 3; ++b) { + + /* smoothing + */ + switch( gfc->VBR->smooth ) { + default: + case 0: + break; + + case 1: + /* make working copy, get min value, select_kth_int will reorder! + */ + for (vbrmn = +10000, sfb = 0; sfb < SBMAX_s; ++sfb) { + sf_cache[sfb] = vbrsf->s[sfb][b]; + if (vbrmn > vbrsf->s[sfb][b]) + vbrmn = vbrsf->s[sfb][b]; + } + + /* find median value, take it as mean + */ + vbrmean = select_kth_int (sf_cache, SBMAX_s, (SBMAX_s+1)/2); + + /* cut peaks + */ + for (sfb = 0; sfb < SBMAX_s; ++sfb) { + if (vbrsf->s[sfb][b] > vbrmean+(vbrmean-vbrmn)) + vbrsf->s[sfb][b] = vbrmean+(vbrmean-vbrmn); + } + break; + + case 2: + for (sfb = 0; sfb < SBMAX_s; ++sfb) { + if (sfb > 0) + if (vbrsf->s[sfb][b] > vbrsf->s[sfb-1][b]+MAX_SF_DELTA) + vbrsf->s[sfb][b] = vbrsf->s[sfb-1][b]+MAX_SF_DELTA; + if (sfb < SBMAX_s-1) + if (vbrsf->s[sfb][b] > vbrsf->s[sfb+1][b]+MAX_SF_DELTA) + vbrsf->s[sfb][b] = vbrsf->s[sfb+1][b]+MAX_SF_DELTA; + } + break; + } + + /* get max value + */ + for (sfb = 0; sfb < SBMAX_s; ++sfb) { + if (*vbrmax < vbrsf->s[sfb][b]) + *vbrmax = vbrsf->s[sfb][b]; + if (*vbrmin > vbrsf->s[sfb][b]) + *vbrmin = vbrsf->s[sfb][b]; + } + } +} + + + /* a variation for vbr-mtrh */ +static void +long_block_sf ( + const lame_internal_flags * gfc, + const III_psy_xmin * l3_xmin, + const FLOAT8 * xr34_orig, + const FLOAT8 * xr34, + III_scalefac_t * vbrsf, + int * vbrmin, + int * vbrmax ) +{ + int sfb; + int vbrmean, vbrmn; + int sf_cache[SBMAX_l]; + int scalefac_criteria; + + if (gfc->presetTune.use) { + /* map experimentalX settings to internal selections */ + static char const map[] = {2,1,0,3,6}; + scalefac_criteria = map[gfc->presetTune.quantcomp_current]; + } + else { + scalefac_criteria = gfc->VBR->quality; + } + + for (sfb = 0; sfb < SBMAX_l; ++sfb) { + const int start = gfc->scalefac_band.l[ sfb ]; + const int end = gfc->scalefac_band.l[ sfb+1 ]; + const int width = end - start; + + switch( scalefac_criteria ) { + default: + /* the fastest + */ + vbrsf->l[sfb] = calc_scalefac( l3_xmin->l[sfb], width, + gfc->presetTune.quantcomp_adjust_mtrh ); + break; + case 5: + case 4: + case 3: + /* the faster and sloppier mode to use at lower quality + */ + vbrsf->l[sfb] = find_scalefac (&xr34[start], &xr34_orig[start], + l3_xmin->l[sfb], width); + break; + case 2: + /* the slower and better mode to use at higher quality + */ + vbrsf->l[sfb] = find_scalefac_ave (&xr34[start], &xr34_orig[start], + l3_xmin->l[sfb], width); + break; + case 1: + /* maxnoise mode to use at higher quality + */ + vbrsf->l[sfb] = find_scalefac_mq (&xr34[start], &xr34_orig[start], + l3_xmin->l[sfb], width, + 1, gfc->VBR->scratch); + break; + case 0: + /* maxnoise mode to use at higher quality + */ + vbrsf->l[sfb] = find_scalefac_mq (&xr34[start], &xr34_orig[start], + l3_xmin->l[sfb], width, + 0, gfc->VBR->scratch); + break; + } + } + + switch( gfc->VBR->smooth ) { + default: + case 0: + break; + + case 1: + /* make working copy, get min value, select_kth_int will reorder! + */ + for (vbrmn = +10000, sfb = 0; sfb < SBMAX_l; ++sfb) { + sf_cache[sfb] = vbrsf->l[sfb]; + if (vbrmn > vbrsf->l[sfb]) + vbrmn = vbrsf->l[sfb]; + } + /* find median value, take it as mean + */ + vbrmean = select_kth_int (sf_cache, SBMAX_l, (SBMAX_l+1)/2); + + /* cut peaks + */ + for (sfb = 0; sfb < SBMAX_l; ++sfb) { + if (vbrsf->l[sfb] > vbrmean+(vbrmean-vbrmn)) + vbrsf->l[sfb] = vbrmean+(vbrmean-vbrmn); + } + break; + + case 2: + for (sfb = 0; sfb < SBMAX_l; ++sfb) { + if (sfb > 0) + if (vbrsf->l[sfb] > vbrsf->l[sfb-1]+MAX_SF_DELTA) + vbrsf->l[sfb] = vbrsf->l[sfb-1]+MAX_SF_DELTA; + if (sfb < SBMAX_l-1) + if (vbrsf->l[sfb] > vbrsf->l[sfb+1]+MAX_SF_DELTA) + vbrsf->l[sfb] = vbrsf->l[sfb+1]+MAX_SF_DELTA; + } + break; + } + + /* get max value + */ + for (*vbrmin = +10000, *vbrmax = -10000, sfb = 0; sfb < SBMAX_l; ++sfb) { + if (*vbrmax < vbrsf->l[sfb]) + *vbrmax = vbrsf->l[sfb]; + if (*vbrmin > vbrsf->l[sfb]) + *vbrmin = vbrsf->l[sfb]; + } +} + + + +/****************************************************************** + * + * short block scalefacs + * + ******************************************************************/ + +static void +short_block_scalefacs ( + const lame_internal_flags * gfc, + gr_info * cod_info, + III_scalefac_t * scalefac, + III_scalefac_t * vbrsf, + int * VBRmax ) +{ + int sfb, maxsfb, b; + int maxover, maxover0, maxover1, mover; + int v0, v1; + int minsfb; + int vbrmax = *VBRmax; + + maxover0 = 0; + maxover1 = 0; + maxsfb = gfc->sfb21_extra ? SBMAX_s : SBPSY_s; + for (sfb = 0; sfb < maxsfb; ++sfb) { + for (b = 0; b < 3; ++b) { + v0 = (vbrmax - vbrsf->s[sfb][b]) - (4*14 + 2*max_range_short[sfb]); + v1 = (vbrmax - vbrsf->s[sfb][b]) - (4*14 + 4*max_range_short[sfb]); + if (maxover0 < v0) + maxover0 = v0; + if (maxover1 < v1) + maxover1 = v1; + } + } + + if ((gfc->noise_shaping == 2) && (gfc->presetTune.use && !(gfc->presetTune.athadjust_safe_noiseshaping || gfc->ATH->adjust < 1.0))) + /* allow scalefac_scale=1 */ + mover = Min (maxover0, maxover1); + else + mover = maxover0; + + vbrmax -= mover; + maxover0 -= mover; + maxover1 -= mover; + + if (maxover0 == 0) + cod_info->scalefac_scale = 0; + else if (maxover1 == 0) + cod_info->scalefac_scale = 1; + + /* sf = (cod_info->global_gain-210.0) */ + cod_info->global_gain = vbrmax + 210; + assert(cod_info->global_gain < 256); + + if (cod_info->global_gain < 0) { + cod_info->global_gain = 0; + } + else + if (cod_info->global_gain > 255) { + cod_info->global_gain = 255; + } + for (sfb = 0; sfb < SBMAX_s; ++sfb) { + for (b = 0; b < 3; ++b) { + vbrsf->s[sfb][b] -= vbrmax; + } + } + maxover = compute_scalefacs_short (vbrsf->s, cod_info, scalefac->s, + cod_info->subblock_gain); + + assert (maxover <= 0); + + /* adjust global_gain so at least 1 subblock gain = 0 */ + minsfb = 999; /* prepare for minimum search */ + for (b = 0; b < 3; ++b) + if (minsfb > cod_info->subblock_gain[b]) + minsfb = cod_info->subblock_gain[b]; + + if (minsfb > cod_info->global_gain/8) + minsfb = cod_info->global_gain/8; + + vbrmax -= 8*minsfb; + cod_info->global_gain -= 8*minsfb; + + for (b = 0; b < 3; ++b) + cod_info->subblock_gain[b] -= minsfb; + + *VBRmax = vbrmax; +} + + + +/****************************************************************** + * + * long block scalefacs + * + ******************************************************************/ + +static void +long_block_scalefacs ( + const lame_internal_flags * gfc, + gr_info * cod_info, + III_scalefac_t * scalefac, + III_scalefac_t * vbrsf, + int * VBRmax ) +{ + const int * max_rangep; + int sfb, maxsfb; + int maxover, maxover0, maxover1, maxover0p, maxover1p, mover; + int v0, v1, v0p, v1p; + int vbrmax = *VBRmax; + + max_rangep = gfc->is_mpeg1 ? max_range_long : max_range_long_lsf_pretab; + + maxover0 = 0; + maxover1 = 0; + maxover0p = 0; /* pretab */ + maxover1p = 0; /* pretab */ + + maxsfb = gfc->sfb21_extra ? SBMAX_l : SBPSY_l; + for ( sfb = 0; sfb < maxsfb; ++sfb ) { + v0 = (vbrmax - vbrsf->l[sfb]) - 2*max_range_long[sfb]; + v1 = (vbrmax - vbrsf->l[sfb]) - 4*max_range_long[sfb]; + v0p = (vbrmax - vbrsf->l[sfb]) - 2*(max_rangep[sfb]+pretab[sfb]); + v1p = (vbrmax - vbrsf->l[sfb]) - 4*(max_rangep[sfb]+pretab[sfb]); + if (maxover0 < v0) + maxover0 = v0; + if (maxover1 < v1) + maxover1 = v1; + if (maxover0p < v0p) + maxover0p = v0p; + if (maxover1p < v1p) + maxover1p = v1p; + } + + mover = Min (maxover0, maxover0p); + if ((gfc->noise_shaping == 2) && (gfc->presetTune.use && !(gfc->presetTune.athadjust_safe_noiseshaping || gfc->ATH->adjust < 1.0))) { + /* allow scalefac_scale=1 */ + mover = Min (mover, maxover1); + mover = Min (mover, maxover1p); + } + + vbrmax -= mover; + maxover0 -= mover; + maxover0p -= mover; + maxover1 -= mover; + maxover1p -= mover; + + if (maxover0 <= 0) { + cod_info->scalefac_scale = 0; + cod_info->preflag = 0; + vbrmax -= maxover0; + } else if (maxover0p <= 0) { + cod_info->scalefac_scale = 0; + cod_info->preflag = 1; + vbrmax -= maxover0p; + } else if (maxover1 == 0) { + cod_info->scalefac_scale = 1; + cod_info->preflag = 0; + } else if (maxover1p == 0) { + cod_info->scalefac_scale = 1; + cod_info->preflag = 1; + } else { + assert(0); /* this should not happen */ + } + + /* sf = (cod_info->global_gain-210.0) */ + cod_info->global_gain = vbrmax + 210; + assert (cod_info->global_gain < 256); + + if (cod_info->global_gain < 0) { + cod_info->global_gain = 0; + } + else + if (cod_info->global_gain > 255) + cod_info->global_gain = 255; + + for (sfb = 0; sfb < SBMAX_l; ++sfb) + vbrsf->l[sfb] -= vbrmax; + + if ( gfc->is_mpeg1 == 1 ) + maxover = compute_scalefacs_long (vbrsf->l, cod_info, scalefac->l); + else + maxover = compute_scalefacs_long_lsf (vbrsf->l, cod_info, scalefac->l); + + assert (maxover <= 0); + + *VBRmax = vbrmax; +} + + + +/*********************************************************************** + * + * quantize xr34 based on scalefactors + * + * calc_short_block_xr34 + * calc_long_block_xr34 + * + * Mark Taylor 2000-??-?? + * Robert Hegemann 2000-10-20 made functions of them + * + ***********************************************************************/ + +static void +short_block_xr34 ( + const lame_internal_flags * gfc, + const gr_info * cod_info, + const III_scalefac_t * scalefac, + const FLOAT8 * xr34_orig, + FLOAT8 * xr34 ) +{ + int sfb, l, j, b; + int ifac, ifqstep, start, end; + FLOAT8 fac; + + /* even though there is no scalefactor for sfb12 + * subblock gain affects upper frequencies too, that's why + * we have to go up to SBMAX_s + */ + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + for ( j = 0, sfb = 0; sfb < SBMAX_s; ++sfb ) { + start = gfc->scalefac_band.s[ sfb ]; + end = gfc->scalefac_band.s[ sfb+1 ]; + for (b = 0; b < 3; ++b) { + ifac = 8*cod_info->subblock_gain[b]+ifqstep*scalefac->s[sfb][b]; + + if ( ifac == 0 ) { /* just copy */ + l = (end-start+7) / 8; + switch ((end-start) % 8) { + default: + case 0: do{ xr34[j] = xr34_orig[j]; ++j; + case 7: xr34[j] = xr34_orig[j]; ++j; + case 6: xr34[j] = xr34_orig[j]; ++j; + case 5: xr34[j] = xr34_orig[j]; ++j; + case 4: xr34[j] = xr34_orig[j]; ++j; + case 3: xr34[j] = xr34_orig[j]; ++j; + case 2: xr34[j] = xr34_orig[j]; ++j; + case 1: xr34[j] = xr34_orig[j]; ++j; } while (--l); + } + continue; + } + if (ifac < Q_MAX-210) + fac = IIPOW20_(ifac); + else + fac = pow (2.0, 0.1875*ifac); + + /* + * loop unrolled into "Duff's Device". Robert Hegemann + */ + l = (end-start+7) / 8; + switch ((end-start) % 8) { + default: + case 0: do{ xr34[j] = xr34_orig[j]*fac; ++j; + case 7: xr34[j] = xr34_orig[j]*fac; ++j; + case 6: xr34[j] = xr34_orig[j]*fac; ++j; + case 5: xr34[j] = xr34_orig[j]*fac; ++j; + case 4: xr34[j] = xr34_orig[j]*fac; ++j; + case 3: xr34[j] = xr34_orig[j]*fac; ++j; + case 2: xr34[j] = xr34_orig[j]*fac; ++j; + case 1: xr34[j] = xr34_orig[j]*fac; ++j; } while (--l); + } + } + } +} + + + +static void +long_block_xr34 ( + const lame_internal_flags * gfc, + const gr_info * cod_info, + const III_scalefac_t * scalefac, + const FLOAT8 * xr34_orig, + FLOAT8 * xr34 ) +{ + int sfb, l, j; + int ifac, ifqstep, start, end; + FLOAT8 fac; + + ifqstep = ( cod_info->scalefac_scale == 0 ) ? 2 : 4; + for ( sfb = 0; sfb < SBMAX_l; ++sfb ) { + + ifac = ifqstep*scalefac->l[sfb]; + if (cod_info->preflag) + ifac += ifqstep*pretab[sfb]; + + start = gfc->scalefac_band.l[ sfb ]; + end = gfc->scalefac_band.l[ sfb+1 ]; + + if ( ifac == 0 ) { /* just copy */ + j = start; + l = (end-start+7) / 8; + switch ((end-start) % 8) { + default: + case 0: do{ xr34[j] = xr34_orig[j]; ++j; + case 7: xr34[j] = xr34_orig[j]; ++j; + case 6: xr34[j] = xr34_orig[j]; ++j; + case 5: xr34[j] = xr34_orig[j]; ++j; + case 4: xr34[j] = xr34_orig[j]; ++j; + case 3: xr34[j] = xr34_orig[j]; ++j; + case 2: xr34[j] = xr34_orig[j]; ++j; + case 1: xr34[j] = xr34_orig[j]; ++j; } while (--l); + } + continue; + } + if (ifac < Q_MAX-210) + fac = IIPOW20_(ifac); + else + fac = pow (2.0, 0.1875*ifac); + + /* + * loop unrolled into "Duff's Device". Robert Hegemann + */ + j = start; + l = (end-start+7) / 8; + switch ((end-start) % 8) { + default: + case 0: do{ xr34[j] = xr34_orig[j]*fac; ++j; + case 7: xr34[j] = xr34_orig[j]*fac; ++j; + case 6: xr34[j] = xr34_orig[j]*fac; ++j; + case 5: xr34[j] = xr34_orig[j]*fac; ++j; + case 4: xr34[j] = xr34_orig[j]*fac; ++j; + case 3: xr34[j] = xr34_orig[j]*fac; ++j; + case 2: xr34[j] = xr34_orig[j]*fac; ++j; + case 1: xr34[j] = xr34_orig[j]*fac; ++j; } while (--l); + } + } +} + + + + + + + +/************************************************************************ + * + * VBR_noise_shaping2() + * + * may result in a need of too many bits, then do it CBR like + * + * Robert Hegemann 2000-10-25 + * + ***********************************************************************/ + +int +VBR_noise_shaping2 ( + lame_global_flags * gfp, + FLOAT8 * xr, + FLOAT8 * xr34orig, + int * l3_enc, + int minbits, + int maxbits, + III_scalefac_t * scalefac, + III_psy_xmin * l3_xmin, + int gr, + int ch ) +{ + lame_internal_flags *gfc = gfp->internal_flags; + III_scalefac_t vbrsf; + III_scalefac_t vbrsf2; + gr_info *cod_info; + FLOAT8 xr34[576]; + int shortblock, ret, bits, huffbits; + int vbrmin, vbrmax, vbrmin2, vbrmax2; + int best_huffman = gfc->use_best_huffman; + int count=6; + + gfc->use_best_huffman = 0; /* we will do it later */ + + cod_info = &gfc->l3_side.gr[gr].ch[ch].tt; + shortblock = (cod_info->block_type == SHORT_TYPE); + + if (shortblock) { + short_block_sf (gfc, l3_xmin, xr34orig, xr, &vbrsf2, &vbrmin2, &vbrmax2); + } else { + long_block_sf (gfc, l3_xmin, xr34orig, xr, &vbrsf2, &vbrmin2, &vbrmax2); + } + vbrsf = vbrsf2; + vbrmin = vbrmin2; + vbrmax = vbrmax2; + +do { +--count; + + if (shortblock) { + short_block_scalefacs (gfc, cod_info, scalefac, &vbrsf, &vbrmax); + short_block_xr34 (gfc, cod_info, scalefac, xr34orig, xr34); + } else { + long_block_scalefacs (gfc, cod_info, scalefac, &vbrsf, &vbrmax); + long_block_xr34 (gfc, cod_info, scalefac, xr34orig, xr34); + } + + ret = VBR_quantize_granule (gfc, xr34, l3_enc, scalefac, gr, ch); + + if (vbrmin == vbrmax) break; + else if (cod_info->part2_3_length < minbits) { + int i; + vbrmax = vbrmin2 + (vbrmax2-vbrmin2) * count/6; + vbrmin = vbrmin2; + if (shortblock) { + for (i = 0; i < SBMAX_s; ++i) { + //vbrsf.s[i][0] = vbrmin2 + (vbrsf2.s[i][0]-vbrmin2) * count/6; + //vbrsf.s[i][1] = vbrmin2 + (vbrsf2.s[i][1]-vbrmin2) * count/6; + //vbrsf.s[i][2] = vbrmin2 + (vbrsf2.s[i][2]-vbrmin2) * count/6; + vbrsf.s[i][0] = Min(vbrsf2.s[i][0], vbrmax); + vbrsf.s[i][1] = Min(vbrsf2.s[i][1], vbrmax); + vbrsf.s[i][2] = Min(vbrsf2.s[i][2], vbrmax); + } + } + else { + for (i = 0; i < SBMAX_l; ++i) { + //vbrsf.l[i] = vbrmin2 + (vbrsf2.l[i]-vbrmin2) * count/6; + vbrsf.l[i] = Min(vbrsf2.l[i], vbrmax); + } + } + } + else if (cod_info->part2_3_length > maxbits) { + int i; + vbrmax = vbrmax2; + vbrmin = vbrmax2 + (vbrmin2-vbrmax2) * count/6; + if (shortblock) { + for (i = 0; i < SBMAX_s; ++i) { + //vbrsf.s[i][0] = vbrmax2 + (vbrsf2.s[i][0]-vbrmax2) * count/6; + //vbrsf.s[i][1] = vbrmax2 + (vbrsf2.s[i][1]-vbrmax2) * count/6; + //vbrsf.s[i][2] = vbrmax2 + (vbrsf2.s[i][2]-vbrmax2) * count/6; + vbrsf.s[i][0] = Max(vbrsf2.s[i][0], vbrmin); + vbrsf.s[i][1] = Max(vbrsf2.s[i][1], vbrmin); + vbrsf.s[i][2] = Max(vbrsf2.s[i][2], vbrmin); + } + } + else { + for (i = 0; i < SBMAX_l; ++i) { + //vbrsf.l[i] = vbrmax2 + (vbrsf2.l[i]-vbrmax2) * count/6; + vbrsf.l[i] = Max(vbrsf2.l[i], vbrmin); + } + } + } + else break; +} while(1 && ret != -1); + + + gfc->use_best_huffman = best_huffman; + + if (ret == -1) /* Houston, we have a problem */ + return -1; + + if (cod_info->part2_3_length < minbits) { + huffbits = minbits - cod_info->part2_length; + bits = bin_search_StepSize (gfc, cod_info, huffbits, + gfc->OldValue[ch], xr34, l3_enc); + gfc->OldValue[ch] = cod_info->global_gain; + cod_info->part2_3_length = bits + cod_info->part2_length; + } + if (cod_info->part2_3_length > maxbits) { + huffbits = maxbits - cod_info->part2_length; + if (huffbits < 0) huffbits = 0; + bits = bin_search_StepSize (gfc, cod_info, huffbits, + gfc->OldValue[ch], xr34, l3_enc); + gfc->OldValue[ch] = cod_info->global_gain; + cod_info->part2_3_length = bits; + if (bits > huffbits) { + bits = inner_loop (gfc, cod_info, huffbits, xr34, l3_enc); + cod_info->part2_3_length = bits; + } + if (bits >= LARGE_BITS) /* Houston, we have a problem */ + return -2; + cod_info->part2_3_length += cod_info->part2_length; + } + + if (cod_info->part2_length >= LARGE_BITS) /* Houston, we have a problem */ + return -2; + + assert (cod_info->global_gain < 256); + + return 0; +} + + + + + + +/************************************************************************ + * + * VBR_noise_shaping() + * + * compute scalefactors, l3_enc, and return number of bits needed to encode + * + * return code: 0 scalefactors were found with all noise < masking + * + * n>0 scalefactors required too many bits. global gain + * was decreased by n + * If n is large, we should probably recompute scalefacs + * with a lower quality. + * + * n<0 scalefactors used less than minbits. + * global gain was increased by n. + * If n is large, might want to recompute scalefacs + * with a higher quality setting? + * + ************************************************************************/ +static int +VBR_noise_shaping ( + lame_global_flags *gfp, + FLOAT8 xr [576], + FLOAT8 xr34orig [576], + int l3_enc [576], + int digital_silence, + int minbits, + int maxbits, + III_scalefac_t *scalefac, + III_psy_xmin *l3_xmin, + int gr, + int ch ) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_scalefac_t save_sf; + III_scalefac_t vbrsf; + gr_info *cod_info; + FLOAT8 xr34[576]; + int shortblock; + int vbrmax, vbrmin; + int global_gain_adjust = 0; + + cod_info = &gfc->l3_side.gr[gr].ch[ch].tt; + shortblock = (cod_info->block_type == SHORT_TYPE); + + if (shortblock) + short_block_sf (gfc, l3_xmin, xr34orig, xr, &vbrsf, &vbrmin, &vbrmax); + else + long_block_sf (gfc, l3_xmin, xr34orig, xr, &vbrsf, &vbrmin, &vbrmax); + + /* save a copy of vbrsf, incase we have to recomptue scalefacs */ + memcpy (&save_sf, &vbrsf, sizeof(III_scalefac_t)); + + do { + memset (scalefac, 0, sizeof(III_scalefac_t)); + + if (shortblock) { + short_block_scalefacs (gfc, cod_info, scalefac, &vbrsf, &vbrmax); + short_block_xr34 (gfc, cod_info, scalefac, xr34orig, xr34); + } else { + long_block_scalefacs (gfc, cod_info, scalefac, &vbrsf, &vbrmax); + long_block_xr34 (gfc, cod_info, scalefac, xr34orig, xr34); + } + VBR_quantize_granule (gfc, xr34, l3_enc, scalefac, gr, ch); + + + /* decrease noise until we use at least minbits + */ + if (cod_info->part2_3_length < minbits) { + if (digital_silence) break; + //if (cod_info->part2_3_length == cod_info->part2_length) break; + if (vbrmax+210 == 0) break; + + /* decrease global gain, recompute scale factors */ + --vbrmax; + --global_gain_adjust; + memcpy (&vbrsf, &save_sf, sizeof(III_scalefac_t)); + } + + } while (cod_info->part2_3_length < minbits); + + /* inject noise until we meet our bit limit + */ + while (cod_info->part2_3_length > Min (maxbits, MAX_BITS)) { + /* increase global gain, keep existing scale factors */ + ++cod_info->global_gain; + if (cod_info->global_gain > 255) + ERRORF (gfc,"%ld impossible to encode ??? frame! bits=%d\n", + // gfp->frameNum, cod_info->part2_3_length); + -1, cod_info->part2_3_length); + VBR_quantize_granule (gfc, xr34, l3_enc, scalefac, gr, ch); + + ++global_gain_adjust; + } + + return global_gain_adjust; +} + + + +void +VBR_quantize(lame_global_flags *gfp, + FLOAT8 pe[2][2], FLOAT8 ms_ener_ratio[2], + FLOAT8 xr[2][2][576], III_psy_ratio ratio[2][2], + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2]) +{ + lame_internal_flags *gfc=gfp->internal_flags; + III_psy_xmin l3_xmin[2][2]; + int minbits,maxbits,max_frame_bits,totbits,gr,ch,i,bits_ok; + int bitsPerFrame,mean_bits; + int analog_silence; + FLOAT8 qadjust; + III_side_info_t * l3_side; + gr_info *cod_info; + int digital_silence[2][2]; + FLOAT8 masking_lower_db=0; + FLOAT8 xr34[2][2][576]; + + qadjust=0; /* start with -1 db quality improvement over quantize.c VBR */ + + l3_side = &gfc->l3_side; + + /* now find out: if the frame can be considered analog silent + * if each granule can be considered digital silent + * and calculate l3_xmin and the fresh xr34 array + */ + + assert( gfp->VBR_q <= 9 ); + assert( gfp->VBR_q >= 0 ); + analog_silence=1; + for (gr = 0; gr < gfc->mode_gr; ++gr) { + /* copy data to be quantized into xr */ + if (gfc->mode_ext==MPG_MD_MS_LR) { + ms_convert(xr[gr],xr[gr]); + } + for (ch = 0; ch < gfc->channels_out; ++ch) { + /* if in the following sections the quality would not be adjusted + * then we would only have to call calc_xmin once here and + * could drop subsequently calls (rh 2000/07/17) + */ + int over_ath; + cod_info = &l3_side->gr[gr].ch[ch].tt; + cod_info->part2_3_length=LARGE_BITS; + + if (cod_info->block_type == SHORT_TYPE) { + cod_info->sfb_lmax = 0; /* No sb*/ + cod_info->sfb_smin = 0; + } else { + /* MPEG 1 doesnt use last scalefactor band */ + cod_info->sfb_lmax = SBPSY_l; + cod_info->sfb_smin = SBPSY_s; /* No sb */ + if (cod_info->mixed_block_flag) { + cod_info->sfb_lmax = gfc->is_mpeg1 ? 8 : 6; + cod_info->sfb_smin = 3; + } + } + + /* quality setting */ + masking_lower_db = gfc->VBR->mask_adjust; + if (pe[gr][ch]>750) { + masking_lower_db -= Min(10,4*(pe[gr][ch]-750.)/750.); + } + gfc->masking_lower = pow(10.0,masking_lower_db/10); + + /* masking thresholds */ + over_ath = calc_xmin(gfp,xr[gr][ch],&ratio[gr][ch],cod_info,&l3_xmin[gr][ch]); + + /* if there are bands with more energy than the ATH + * then we say the frame is not analog silent */ + if (over_ath) { + analog_silence = 0; + } + + /* if there is no line with more energy than 1e-20 + * then this granule is considered to be digital silent + * plus calculation of xr34 */ + digital_silence[gr][ch] = 1; + for(i=0;i<576;++i) { + FLOAT8 temp=fabs(xr[gr][ch][i]); + xr34[gr][ch][i]=sqrt(sqrt(temp)*temp); + digital_silence[gr][ch] &= temp < 1E-20; + } + } /* ch */ + } /* gr */ + + + /* compute minimum allowed bits from minimum allowed bitrate */ + if (analog_silence) { + gfc->bitrate_index=1; + } else { + gfc->bitrate_index=gfc->VBR_min_bitrate; + } + getframebits(gfp, &bitsPerFrame, &mean_bits); + minbits = (mean_bits/gfc->channels_out); + + /* compute maximum allowed bits from max allowed bitrate */ + gfc->bitrate_index=gfc->VBR_max_bitrate; + getframebits(gfp, &bitsPerFrame, &mean_bits); + max_frame_bits = ResvFrameBegin(gfp, l3_side, mean_bits, bitsPerFrame); + maxbits=2.5*(mean_bits/gfc->channels_out); + + { + /* compute a target mean_bits based on compression ratio + * which was set based on VBR_q + */ + int bit_rate = gfp->out_samplerate*16*gfc->channels_out/(1000.0*gfp->compression_ratio); + bitsPerFrame = (bit_rate*gfp->framesize*1000)/gfp->out_samplerate; + mean_bits = (bitsPerFrame - 8*gfc->sideinfo_len) / gfc->mode_gr; + } + + + minbits = Max(minbits,125); + minbits=Max(minbits,.40*(mean_bits/gfc->channels_out)); + maxbits=Min(maxbits,2.5*(mean_bits/gfc->channels_out)); + + + + + + + + /* + * loop over all ch,gr, encoding anything with bits > .5*(max_frame_bits/4) + * + * If a particular granule uses way too many bits, it will be re-encoded + * on the next iteration of the loop (with a lower quality setting). + * But granules which dont use + * use too many bits will not be re-encoded. + * + * minbits: minimum allowed bits for 1 granule 1 channel + * maxbits: maximum allowwed bits for 1 granule 1 channel + * max_frame_bits: maximum allowed bits for entire frame + * (max_frame_bits/4) estimate of average bits per granule per channel + * + */ + + do { + + totbits=0; + for (gr = 0; gr < gfc->mode_gr; ++gr) { + int minbits_lr[2]; + minbits_lr[0]=minbits; + minbits_lr[1]=minbits; + +#if 0 + if (gfc->mode_ext==MPG_MD_MS_LR) { + FLOAT8 fac; + fac = .33*(.5-ms_ener_ratio[gr])/.5; + if (fac<0) fac=0; + if (fac>.5) fac=.5; + minbits_lr[0] = (1+fac)*minbits; + minbits_lr[1] = Max(125,(1-fac)*minbits); + } +#endif + + + for (ch = 0; ch < gfc->channels_out; ++ch) { + int adjusted,shortblock; + cod_info = &l3_side->gr[gr].ch[ch].tt; + + /* ENCODE this data first pass, and on future passes unless it uses + * a very small percentage of the max_frame_bits */ + if (cod_info->part2_3_length > (max_frame_bits/(2*gfc->channels_out*gfc->mode_gr))) { + + shortblock = (cod_info->block_type == SHORT_TYPE); + + /* Adjust allowed masking based on quality setting */ + if (qadjust!=0 /*|| shortblock*/) { + masking_lower_db = gfc->VBR->mask_adjust + qadjust; + + /* + if (shortblock) masking_lower_db -= 4; + */ + + if (pe[gr][ch]>750) + masking_lower_db -= Min(10,4*(pe[gr][ch]-750.)/750.); + gfc->masking_lower = pow(10.0,masking_lower_db/10); + calc_xmin( gfp, xr[gr][ch], ratio[gr]+ch, cod_info, l3_xmin[gr]+ch); + } + + /* digital silent granules do not need the full round trip, + * but this can be optimized later on + */ + adjusted = VBR_noise_shaping (gfp,xr[gr][ch],xr34[gr][ch], + l3_enc[gr][ch], + digital_silence[gr][ch], + minbits_lr[ch], + maxbits,scalefac[gr]+ch, + l3_xmin[gr]+ch,gr,ch); + if (adjusted>10) { + /* global_gain was changed by a large amount to get bits < maxbits */ + /* quality is set to high. we could set bits = LARGE_BITS + * to force re-encoding. But most likely the other channels/granules + * will also use too many bits, and the entire frame will + * be > max_frame_bits, forcing re-encoding below. + */ + // cod_info->part2_3_bits = LARGE_BITS; + } + } + totbits += cod_info->part2_3_length; + } + } + bits_ok=1; + if (totbits>max_frame_bits) { + /* lower quality */ + qadjust += Max(.125,Min(1,(totbits-max_frame_bits)/300.0)); + /* adjusting minbits and maxbits is necessary too + * cos lowering quality is not enough in rare cases + * when each granule still needs almost maxbits, it wont fit */ + minbits = Max(125,minbits*0.975); + maxbits = Max(minbits,maxbits*0.975); + // DEBUGF("%i totbits>max_frame_bits totbits=%i maxbits=%i \n",gfp->frameNum,totbits,max_frame_bits); + // DEBUGF("next masking_lower_db = %f \n",masking_lower_db + qadjust); + bits_ok=0; + } + + } while (!bits_ok); + + + + /* find optimal scalefac storage. Cant be done above because + * might enable scfsi which breaks the interation loops */ + totbits=0; + for (gr = 0; gr < gfc->mode_gr; ++gr) { + for (ch = 0; ch < gfc->channels_out; ++ch) { + best_scalefac_store(gfc, gr, ch, l3_enc, l3_side, scalefac); + totbits += l3_side->gr[gr].ch[ch].tt.part2_3_length; + } + } + + + + + if (analog_silence && !gfp->VBR_hard_min) { + gfc->bitrate_index = 1; + } else { + gfc->bitrate_index = gfc->VBR_min_bitrate; + } + for( ; gfc->bitrate_index < gfc->VBR_max_bitrate; ++gfc->bitrate_index ) { + + getframebits (gfp, &bitsPerFrame, &mean_bits); + maxbits = ResvFrameBegin(gfp, l3_side, mean_bits, bitsPerFrame); + if (totbits <= maxbits) break; + } + if (gfc->bitrate_index == gfc->VBR_max_bitrate) { + getframebits (gfp, &bitsPerFrame, &mean_bits); + maxbits = ResvFrameBegin(gfp, l3_side, mean_bits, bitsPerFrame); + } + + // DEBUGF("%i total_bits=%i max_frame_bits=%i index=%i \n",gfp->frameNum,totbits,max_frame_bits,gfc->bitrate_index); + + for (gr = 0; gr < gfc->mode_gr; ++gr) { + for (ch = 0; ch < gfc->channels_out; ++ch) { + cod_info = &l3_side->gr[gr].ch[ch].tt; + + + ResvAdjust (gfc, cod_info, l3_side, mean_bits); + + /******************************************************************* + * set the sign of l3_enc from the sign of xr + *******************************************************************/ + for ( i = 0; i < 576; ++i) { + if (xr[gr][ch][i] < 0) l3_enc[gr][ch][i] *= -1; + } + } + } + ResvFrameEnd (gfc, l3_side, mean_bits); + + + +} + + + + diff --git a/lib/lame/vbrquantize.h b/lib/lame/vbrquantize.h new file mode 100644 index 0000000..9eff403 --- /dev/null +++ b/lib/lame/vbrquantize.h @@ -0,0 +1,47 @@ +/* + * MP3 VBR quantization + * + * Copyright (c) 1999 Mark Taylor + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_VBRQUANTIZE_H +#define LAME_VBRQUANTIZE_H + +void VBR_quantize( + lame_global_flags *gfp, + FLOAT8 pe[2][2], + FLOAT8 ms_ener_ratio[2], + FLOAT8 xr[2][2][576], + III_psy_ratio ratio[2][2], + int l3_enc[2][2][576], + III_scalefac_t scalefac[2][2]); + + +int VBR_noise_shaping2( + lame_global_flags * gfp, + FLOAT8 * xr, + FLOAT8 * xr34orig, + int * l3_enc, + int minbits, + int maxbits, + III_scalefac_t * scalefac, + III_psy_xmin * l3_xmin, + int gr, + int ch ); + +#endif /* LAME_VBRQUANTIZE_H */ diff --git a/lib/lame/version.c b/lib/lame/version.c new file mode 100644 index 0000000..f5e45e9 --- /dev/null +++ b/lib/lame/version.c @@ -0,0 +1,214 @@ +/* + * Version numbering for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +/*! + \file version.c + \brief Version numbering for LAME. + + Contains functions which describe the version of LAME. + + \author A.L. Faber + \version \$Id: version.c,v 1.1 2002/04/28 17:30:31 kramm Exp $ + \ingroup libmp3lame +*/ + + +#include "config_static.h" + + +#include +#include "version.h" /* macros of version numbers */ + +#ifdef WITH_DMALLOC +#include +#endif + +//! Stringify \a x. +#define STR(x) #x +//! Stringify \a x, perform macro expansion. +#define XSTR(x) STR(x) + +#if defined(MMX_choose_table) +# define V1 "MMX " +#else +# define V1 "" +#endif + +#if defined(KLEMM) +# define V2 "KLM " +#else +# define V2 "" +#endif + +#if defined(RH) +# define V3 "RH " +#else +# define V3 "" +#endif + +//! Compile time features. +#define V V1 V2 V3 + +//! Get the LAME version string. +/*! + \param void + \return a pointer to a string which describes the version of LAME. +*/ +const char* get_lame_version ( void ) /* primary to write screen reports */ +{ + /* Here we can also add informations about compile time configurations */ + +#if LAME_ALPHA_VERSION > 0 + static /*@observer@*/ const char *const str = + XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) " " V + "(alpha " XSTR(LAME_ALPHA_VERSION) ", " __DATE__ " " __TIME__ ")"; +#elif LAME_BETA_VERSION > 0 + static /*@observer@*/ const char *const str = + XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) " " V + "(beta " XSTR(LAME_BETA_VERSION) ", " __DATE__ ")"; +#else + static /*@observer@*/ const char *const str = + XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) " " V; +#endif + + return str; +} + + +//! Get the short LAME version string. +/*! + It's mainly for inclusion into the MP3 stream. + + \param void + \return a pointer to the short version of the LAME version string. +*/ +const char* get_lame_short_version ( void ) +{ + /* adding date and time to version string makes it harder for output + validation */ + +#if LAME_ALPHA_VERSION > 0 + static /*@observer@*/ const char *const str = + XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) " (alpha)"; +#elif LAME_BETA_VERSION > 0 + static /*@observer@*/ const char *const str = + XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) " (beta)"; +#else + static /*@observer@*/ const char *const str = + XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION); +#endif + + return str; +} + +//! Get the _very_ short LAME version string. +/*! + It's used in the LAME VBR tag only. + + \param void + \return a pointer to the short version of the LAME version string. +*/ +const char* get_lame_very_short_version ( void ) +{ + /* adding date and time to version string makes it harder for output + validation */ + +#if LAME_ALPHA_VERSION > 0 + static /*@observer@*/ const char *const str = + "LAME" XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) "a"; +#elif LAME_BETA_VERSION > 0 + static /*@observer@*/ const char *const str = + "LAME" XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) "b"; +#else + static /*@observer@*/ const char *const str = + "LAME" XSTR(LAME_MAJOR_VERSION) "." XSTR(LAME_MINOR_VERSION) " "; +#endif + + return str; +} + +//! Get the version string for GPSYCHO. +/*! + \param void + \return a pointer to a string which describes the version of GPSYCHO. +*/ +const char* get_psy_version ( void ) +{ +#if PSY_ALPHA_VERSION > 0 + static /*@observer@*/ const char *const str = + XSTR(PSY_MAJOR_VERSION) "." XSTR(PSY_MINOR_VERSION) + " (alpha " XSTR(PSY_ALPHA_VERSION) ", " __DATE__ " " __TIME__ ")"; +#elif PSY_BETA_VERSION > 0 + static /*@observer@*/ const char *const str = + XSTR(PSY_MAJOR_VERSION) "." XSTR(PSY_MINOR_VERSION) + " (beta " XSTR(PSY_BETA_VERSION) ", " __DATE__ ")"; +#else + static /*@observer@*/ const char *const str = + XSTR(PSY_MAJOR_VERSION) "." XSTR(PSY_MINOR_VERSION); +#endif + + return str; +} + + +//! Get the URL for the LAME website. +/*! + \param void + \return a pointer to a string which is a URL for the LAME website. +*/ +const char* get_lame_url ( void ) +{ + static /*@observer@*/ const char *const str = LAME_URL; + + return str; +} + + +//! Get the numerical representation of the version. +/*! + Writes the numerical representation of the version of LAME and + GPSYCHO into lvp. + + \param lvp +*/ +void get_lame_version_numerical ( lame_version_t *const lvp ) +{ + static /*@observer@*/ const char *const features = V; + + /* generic version */ + lvp->major = LAME_MAJOR_VERSION; + lvp->minor = LAME_MINOR_VERSION; + lvp->alpha = LAME_ALPHA_VERSION; + lvp->beta = LAME_BETA_VERSION; + + /* psy version */ + lvp->psy_major = PSY_MAJOR_VERSION; + lvp->psy_minor = PSY_MINOR_VERSION; + lvp->psy_alpha = PSY_ALPHA_VERSION; + lvp->psy_beta = PSY_BETA_VERSION; + + /* compile time features */ + /*@-mustfree@*/ + lvp->features = features; + /*@=mustfree@*/ +} + +/* end of version.c */ diff --git a/lib/lame/version.h b/lib/lame/version.h new file mode 100644 index 0000000..2b8a9e5 --- /dev/null +++ b/lib/lame/version.h @@ -0,0 +1,55 @@ +/* + * Version numbering for LAME. + * + * Copyright (c) 1999 A.L. Faber + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 Library 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. + */ + +#ifndef LAME_VERSION_H +#define LAME_VERSION_H + +# include "lame.h" + +/* + * To make a string from a token, use the # operator: + * + * #define __STR(x) #x + * #define STR(x) __STR(x) + */ + +# define LAME_URL "http://www.mp3dev.org/" + +# define LAME_MAJOR_VERSION 3 /* Major version number */ +# define LAME_MINOR_VERSION 91 /* Minor version number */ +# define LAME_ALPHA_VERSION 0 /* Patch level of alpha version, otherwise zero */ +# define LAME_BETA_VERSION 0 /* Patch level of beta version, otherwise zero */ + +# define PSY_MAJOR_VERSION 0 /* Major version number */ +# define PSY_MINOR_VERSION 89 /* Minor version number */ +# define PSY_ALPHA_VERSION 0 /* Set number if this is an alpha version, otherwise zero */ +# define PSY_BETA_VERSION 0 /* Set number if this is a beta version, otherwise zero */ + + +const char* get_lame_version ( void ); +const char* get_lame_short_version ( void ); +const char* get_psy_version ( void ); +const char* get_lame_url ( void ); +void get_lame_version_numerical ( lame_version_t *const lvp ); + +#endif /* LAME_VERSION_H */ + +/* End of version.h */