| /* |
| * 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. |
| */ |
| |
| |
| #include <assert.h> |
| |
| #ifdef HAVEGTK |
| #include "gtkanal.h" |
| #include <gtk/gtk.h> |
| #endif |
| #include "lame.h" |
| #include "util.h" |
| #include "timestatus.h" |
| #include "psymodel.h" |
| #include "newmdct.h" |
| #include "quantize.h" |
| #include "quantize-pvt.h" |
| #include "l3bitstream.h" |
| #include "formatBitstream.h" |
| #include "version.h" |
| #include "VbrTag.h" |
| #include "id3tag.h" |
| #include "tables.h" |
| #include "brhist.h" |
| #include "get_audio.h" |
| |
| #ifdef __riscos__ |
| #include "asmstuff.h" |
| #endif |
| |
| |
| /* Global variable definitions for lame.c */ |
| static Bit_stream_struc bs; |
| static III_side_info_t l3_side; |
| #define MFSIZE (1152+1152+ENCDELAY-MDCTDELAY) |
| static short int mfbuf[2][MFSIZE]; |
| static int mf_size; |
| static int mf_samples_to_encode; |
| |
| |
| static const char *mybasename(const char *str) { |
| const char *base = strrchr(str, '/'); |
| return base ? base+1 : str; |
| } |
| |
| |
| /******************************************************************** |
| * initialize internal params based on data in gf |
| * (globalflags struct filled in by calling program) |
| * |
| ********************************************************************/ |
| void lame_init_params(lame_global_flags *gfp) |
| { |
| int i; |
| FLOAT compression_ratio; |
| |
| |
| memset(&bs, 0, sizeof(Bit_stream_struc)); |
| memset(&l3_side,0x00,sizeof(III_side_info_t)); |
| |
| |
| gfp->frameNum=0; |
| InitFormatBitStream(); |
| if (gfp->num_channels==1) { |
| gfp->mode = MPG_MD_MONO; |
| } |
| gfp->stereo=2; |
| if (gfp->mode == MPG_MD_MONO) gfp->stereo=1; |
| |
| #ifdef BRHIST |
| if (gfp->silent) { |
| disp_brhist=0; /* turn of VBR historgram */ |
| } |
| if (!gfp->VBR) { |
| disp_brhist=0; /* turn of VBR historgram */ |
| } |
| #endif |
| |
| /* set the output sampling rate, and resample options if necessary |
| samplerate = input sample rate |
| resamplerate = ouput sample rate |
| */ |
| if (gfp->out_samplerate==0) { |
| /* user did not specify output sample rate */ |
| gfp->out_samplerate=gfp->in_samplerate; /* default */ |
| |
| |
| /* if resamplerate is not valid, find a valid value */ |
| if (gfp->out_samplerate>=48000) gfp->out_samplerate=48000; |
| else if (gfp->out_samplerate>=44100) gfp->out_samplerate=44100; |
| else if (gfp->out_samplerate>=32000) gfp->out_samplerate=32000; |
| else if (gfp->out_samplerate>=24000) gfp->out_samplerate=24000; |
| else if (gfp->out_samplerate>=22050) gfp->out_samplerate=22050; |
| else gfp->out_samplerate=16000; |
| |
| |
| if (gfp->brate>0) { |
| /* check if user specified bitrate requires downsampling */ |
| compression_ratio = gfp->out_samplerate*16*gfp->stereo/(1000.0*gfp->brate); |
| if (!gfp->VBR && compression_ratio > 13 ) { |
| /* automatic downsample, if possible */ |
| gfp->out_samplerate = (10*1000.0*gfp->brate)/(16*gfp->stereo); |
| if (gfp->out_samplerate<=16000) gfp->out_samplerate=16000; |
| else if (gfp->out_samplerate<=22050) gfp->out_samplerate=22050; |
| else if (gfp->out_samplerate<=24000) gfp->out_samplerate=24000; |
| else if (gfp->out_samplerate<=32000) gfp->out_samplerate=32000; |
| else if (gfp->out_samplerate<=44100) gfp->out_samplerate=44100; |
| else gfp->out_samplerate=48000; |
| } |
| } |
| } |
| |
| gfp->mode_gr = (gfp->out_samplerate <= 24000) ? 1 : 2; /* mode_gr = 2 */ |
| gfp->encoder_delay = ENCDELAY; |
| gfp->framesize = gfp->mode_gr*576; |
| |
| if (gfp->brate==0) { /* user didn't specify a bitrate, use default */ |
| gfp->brate=128; |
| if (gfp->mode_gr==1) gfp->brate=64; |
| } |
| |
| |
| gfp->resample_ratio=1; |
| if (gfp->out_samplerate != gfp->in_samplerate) gfp->resample_ratio = (FLOAT)gfp->in_samplerate/(FLOAT)gfp->out_samplerate; |
| |
| /* estimate total frames. must be done after setting sampling rate so |
| * we know the framesize. */ |
| gfp->totalframes=0; |
| gfp->totalframes = 2+ gfp->num_samples/(gfp->resample_ratio*gfp->framesize); |
| |
| |
| |
| /* 44.1kHz at 56kbs/channel: compression factor of 12.6 |
| 44.1kHz at 64kbs/channel: compression factor of 11.025 |
| 44.1kHz at 80kbs/channel: compression factor of 8.82 |
| 22.05kHz at 24kbs: 14.7 |
| 22.05kHz at 32kbs: 11.025 |
| 22.05kHz at 40kbs: 8.82 |
| 16kHz at 16kbs: 16.0 |
| 16kHz at 24kbs: 10.7 |
| |
| compression_ratio |
| 11 .70? |
| 12 sox resample .66 |
| 14.7 sox resample .45 |
| |
| */ |
| if (gfp->brate >= 320) gfp->VBR=0; /* dont bother with VBR at 320kbs */ |
| compression_ratio = gfp->out_samplerate*16*gfp->stereo/(1000.0*gfp->brate); |
| |
| |
| /* for VBR, take a guess at the compression_ratio */ |
| /* VBR_q compression like |
| 0 4.4 320kbs |
| 1 5.4 256kbs |
| 3 7.4 192kbs |
| 4 8.8 160kbs |
| 6 10.4 128kbs |
| */ |
| if (gfp->VBR && compression_ratio>11) { |
| compression_ratio = 4.4 + gfp->VBR_q; |
| } |
| |
| |
| /* At higher quality (lower compression) use STEREO instead of JSTEREO. |
| * (unless the user explicitly specified a mode ) */ |
| if ( (!gfp->mode_fixed) && (gfp->mode !=MPG_MD_MONO)) { |
| if (compression_ratio < 9 ) { |
| gfp->mode = MPG_MD_STEREO; |
| } |
| } |
| |
| |
| |
| /****************************************************************/ |
| /* if a filter has not been enabled, see if we should add one: */ |
| /****************************************************************/ |
| if (gfp->lowpassfreq == 0) { |
| /* If the user has not selected their own filter, add a lowpass |
| * filter based on the compression ratio. Formula based on |
| 44.1 /160 4.4x |
| 44.1 /128 5.5x keep all bands |
| 44.1 /96kbs 7.3x keep band 28 |
| 44.1 /80kbs 8.8x keep band 25 |
| 44.1khz/64kbs 11x keep band 21 22? |
| |
| 16khz/24kbs 10.7x keep band 21 |
| 22kHz/32kbs 11x keep band ? |
| 22kHz/24kbs 14.7x keep band 16 |
| 16 16 16x keep band 14 |
| */ |
| |
| |
| /* Should we use some lowpass filters? */ |
| int band = 1+floor(.5 + 14-18*log(compression_ratio/16.0)); |
| if (band < 31) { |
| gfp->lowpass1 = band/31.0; |
| gfp->lowpass2 = band/31.0; |
| } |
| } |
| |
| /****************************************************************/ |
| /* apply user driven filters*/ |
| /****************************************************************/ |
| if ( gfp->highpassfreq > 0 ) { |
| gfp->highpass1 = 2.0*gfp->highpassfreq/gfp->out_samplerate; /* will always be >=0 */ |
| if ( gfp->highpasswidth >= 0 ) { |
| gfp->highpass2 = 2.0*(gfp->highpassfreq+gfp->highpasswidth)/gfp->out_samplerate; |
| } else { |
| /* 15% above on default */ |
| /* gfp->highpass2 = 1.15*2.0*gfp->highpassfreq/gfp->out_samplerate; */ |
| gfp->highpass2 = 1.00*2.0*gfp->highpassfreq/gfp->out_samplerate; |
| } |
| gfp->highpass1 = Min( 1, gfp->highpass1 ); |
| gfp->highpass2 = Min( 1, gfp->highpass2 ); |
| } |
| |
| if ( gfp->lowpassfreq > 0 ) { |
| gfp->lowpass2 = 2.0*gfp->lowpassfreq/gfp->out_samplerate; /* will always be >=0 */ |
| if ( gfp->lowpasswidth >= 0 ) { |
| gfp->lowpass1 = 2.0*(gfp->lowpassfreq-gfp->lowpasswidth)/gfp->out_samplerate; |
| if ( gfp->lowpass1 < 0 ) { /* has to be >= 0 */ |
| gfp->lowpass1 = 0; |
| } |
| } else { |
| /* 15% below on default */ |
| /* gfp->lowpass1 = 0.85*2.0*gfp->lowpassfreq/gfp->out_samplerate; */ |
| gfp->lowpass1 = 1.00*2.0*gfp->lowpassfreq/gfp->out_samplerate; |
| } |
| gfp->lowpass1 = Min( 1, gfp->lowpass1 ); |
| gfp->lowpass2 = Min( 1, gfp->lowpass2 ); |
| } |
| |
| |
| /***************************************************************/ |
| /* compute info needed for polyphase filter */ |
| /***************************************************************/ |
| if (gfp->filter_type==0) { |
| int band,maxband,minband; |
| FLOAT8 amp,freq; |
| if (gfp->lowpass1 > 0) { |
| minband=999; |
| maxband=-1; |
| for (band=0; band <=31 ; ++band) { |
| freq = band/31.0; |
| amp = 1; |
| /* this band and above will be zeroed: */ |
| if (freq >= gfp->lowpass2) { |
| gfp->lowpass_band= Min(gfp->lowpass_band,band); |
| amp=0; |
| } |
| if (gfp->lowpass1 < freq && freq < gfp->lowpass2) { |
| minband = Min(minband,band); |
| maxband = Max(maxband,band); |
| amp = cos((PI/2)*(gfp->lowpass1-freq)/(gfp->lowpass2-gfp->lowpass1)); |
| } |
| /* printf("lowpass band=%i amp=%f \n",band,amp);*/ |
| } |
| /* compute the *actual* transition band implemented by the polyphase filter */ |
| if (minband==999) gfp->lowpass1 = (gfp->lowpass_band-.75)/31.0; |
| else gfp->lowpass1 = (minband-.75)/31.0; |
| gfp->lowpass2 = gfp->lowpass_band/31.0; |
| } |
| |
| /* make sure highpass filter is within 90% of whan the effective highpass |
| * frequency will be */ |
| if (gfp->highpass2 > 0) |
| if (gfp->highpass2 < .9*(.75/31.0) ) { |
| gfp->highpass1=0; gfp->highpass2=0; |
| fprintf(stderr,"Warning: highpass filter disabled. highpass frequency to small\n"); |
| } |
| |
| |
| if (gfp->highpass2 > 0) { |
| minband=999; |
| maxband=-1; |
| for (band=0; band <=31; ++band) { |
| freq = band/31.0; |
| amp = 1; |
| /* this band and below will be zereod */ |
| if (freq <= gfp->highpass1) { |
| gfp->highpass_band = Max(gfp->highpass_band,band); |
| amp=0; |
| } |
| if (gfp->highpass1 < freq && freq < gfp->highpass2) { |
| minband = Min(minband,band); |
| maxband = Max(maxband,band); |
| amp = cos((PI/2)*(gfp->highpass2-freq)/(gfp->highpass2-gfp->highpass1)); |
| } |
| /* printf("highpass band=%i amp=%f \n",band,amp);*/ |
| } |
| /* compute the *actual* transition band implemented by the polyphase filter */ |
| gfp->highpass1 = gfp->highpass_band/31.0; |
| if (maxband==-1) gfp->highpass2 = (gfp->highpass_band+.75)/31.0; |
| else gfp->highpass2 = (maxband+.75)/31.0; |
| } |
| /* |
| printf("lowpass band with amp=0: %i \n",gfp->lowpass_band); |
| printf("highpass band with amp=0: %i \n",gfp->highpass_band); |
| */ |
| } |
| |
| |
| |
| /***************************************************************/ |
| /* compute info needed for FIR filter */ |
| /***************************************************************/ |
| if (gfp->filter_type==1) { |
| } |
| |
| |
| |
| |
| gfp->mode_ext=MPG_MD_LR_LR; |
| gfp->stereo = (gfp->mode == MPG_MD_MONO) ? 1 : 2; |
| |
| |
| gfp->samplerate_index = SmpFrqIndex((long)gfp->out_samplerate, &gfp->version); |
| if( gfp->samplerate_index < 0) { |
| display_bitrates(stderr); |
| exit(1); |
| } |
| if( (gfp->bitrate_index = BitrateIndex(gfp->brate, gfp->version,gfp->out_samplerate)) < 0) { |
| display_bitrates(stderr); |
| exit(1); |
| } |
| |
| |
| /* choose a min/max bitrate for VBR */ |
| if (gfp->VBR) { |
| /* if the user didn't specify VBR_max_bitrate: */ |
| if (0==gfp->VBR_max_bitrate_kbps) { |
| /* default max bitrate is 256kbs */ |
| /* we do not normally allow 320bps frams with VBR, unless: */ |
| gfp->VBR_max_bitrate=13; /* default: allow 256kbs */ |
| if (gfp->VBR_min_bitrate_kbps>=256) gfp->VBR_max_bitrate=14; |
| if (gfp->VBR_q == 0) gfp->VBR_max_bitrate=14; /* allow 320kbs */ |
| if (gfp->VBR_q >= 4) gfp->VBR_max_bitrate=12; /* max = 224kbs */ |
| if (gfp->VBR_q >= 8) gfp->VBR_max_bitrate=9; /* low quality, max = 128kbs */ |
| }else{ |
| if( (gfp->VBR_max_bitrate = BitrateIndex(gfp->VBR_max_bitrate_kbps, gfp->version,gfp->out_samplerate)) < 0) { |
| display_bitrates(stderr); |
| exit(1); |
| } |
| } |
| if (0==gfp->VBR_min_bitrate_kbps) { |
| gfp->VBR_min_bitrate=1; /* 32 kbps */ |
| }else{ |
| if( (gfp->VBR_min_bitrate = BitrateIndex(gfp->VBR_min_bitrate_kbps, gfp->version,gfp->out_samplerate)) < 0) { |
| display_bitrates(stderr); |
| exit(1); |
| } |
| } |
| |
| } |
| |
| |
| if (gfp->VBR) gfp->quality=Min(gfp->quality,2); /* always use quality <=2 with VBR */ |
| /* dont allow forced mid/side stereo for mono output */ |
| if (gfp->mode == MPG_MD_MONO) gfp->force_ms=0; |
| |
| |
| /* Do not write VBR tag if VBR flag is not specified */ |
| if (gfp->VBR==0) gfp->bWriteVbrTag=0; |
| |
| /* some file options not allowed if output is: not specified or stdout */ |
| |
| if (gfp->outPath!=NULL && gfp->outPath[0]=='-' ) { |
| gfp->bWriteVbrTag=0; /* turn off VBR tag */ |
| } |
| |
| if (gfp->outPath==NULL || gfp->outPath[0]=='-' ) { |
| id3tag.used=0; /* turn of id3 tagging */ |
| } |
| |
| |
| |
| if (gfp->gtkflag) { |
| gfp->bWriteVbrTag=0; /* disable Xing VBR tag */ |
| } |
| |
| init_bit_stream_w(&bs); |
| |
| |
| |
| /* set internal feature flags. USER should not access these since |
| * some combinations will produce strange results */ |
| |
| /* no psymodel, no noise shaping */ |
| if (gfp->quality==9) { |
| gfp->filter_type=0; |
| gfp->psymodel=0; |
| gfp->quantization=0; |
| gfp->noise_shaping=0; |
| gfp->noise_shaping_stop=0; |
| gfp->use_best_huffman=0; |
| } |
| |
| if (gfp->quality==8) gfp->quality=7; |
| |
| /* use psymodel (for short block and m/s switching), but no noise shapping */ |
| if (gfp->quality==7) { |
| gfp->filter_type=0; |
| gfp->psymodel=1; |
| gfp->quantization=0; |
| gfp->noise_shaping=0; |
| gfp->noise_shaping_stop=0; |
| gfp->use_best_huffman=0; |
| } |
| |
| if (gfp->quality==6) gfp->quality=5; |
| |
| if (gfp->quality==5) { |
| /* the default */ |
| gfp->filter_type=0; |
| gfp->psymodel=1; |
| gfp->quantization=0; |
| gfp->noise_shaping=1; |
| gfp->noise_shaping_stop=0; |
| gfp->use_best_huffman=0; |
| } |
| |
| if (gfp->quality==4) gfp->quality=2; |
| if (gfp->quality==3) gfp->quality=2; |
| |
| if (gfp->quality==2) { |
| gfp->filter_type=0; |
| gfp->psymodel=1; |
| gfp->quantization=1; |
| gfp->noise_shaping=1; |
| gfp->noise_shaping_stop=0; |
| gfp->use_best_huffman=1; |
| } |
| |
| if (gfp->quality==1) { |
| gfp->filter_type=0; |
| gfp->psymodel=1; |
| gfp->quantization=1; |
| gfp->noise_shaping=1; |
| gfp->noise_shaping_stop=1; |
| gfp->use_best_huffman=1; |
| } |
| |
| if (gfp->quality==0) { |
| /* 0..1 quality */ |
| gfp->filter_type=1; /* not yet coded */ |
| gfp->psymodel=1; |
| gfp->quantization=1; |
| gfp->noise_shaping=3; /* not yet coded */ |
| gfp->noise_shaping_stop=2; /* not yet coded */ |
| gfp->use_best_huffman=2; /* not yet coded */ |
| exit(-99); |
| } |
| |
| |
| for (i = 0; i < SBMAX_l + 1; i++) { |
| scalefac_band.l[i] = |
| sfBandIndex[gfp->samplerate_index + (gfp->version * 3)].l[i]; |
| } |
| for (i = 0; i < SBMAX_s + 1; i++) { |
| scalefac_band.s[i] = |
| sfBandIndex[gfp->samplerate_index + (gfp->version * 3)].s[i]; |
| } |
| |
| |
| |
| if (gfp->bWriteVbrTag) |
| { |
| /* Write initial VBR Header to bitstream */ |
| InitVbrTag(&bs,1-gfp->version,gfp->mode,gfp->samplerate_index); |
| } |
| |
| #ifdef HAVEGTK |
| gtkflag=gfp->gtkflag; |
| #endif |
| |
| #ifdef BRHIST |
| if (gfp->VBR) { |
| if (disp_brhist) |
| brhist_init(gfp,1, 14); |
| } else |
| disp_brhist = 0; |
| #endif |
| return; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| /************************************************************************ |
| * |
| * print_config |
| * |
| * PURPOSE: Prints the encoding parameters used |
| * |
| ************************************************************************/ |
| void lame_print_config(lame_global_flags *gfp) |
| { |
| static const char *mode_names[4] = { "stereo", "j-stereo", "dual-ch", "single-ch" }; |
| FLOAT out_samplerate=gfp->out_samplerate/1000.0; |
| FLOAT in_samplerate = gfp->resample_ratio*out_samplerate; |
| FLOAT compression= |
| (FLOAT)(gfp->stereo*16*out_samplerate)/(FLOAT)(gfp->brate); |
| |
| lame_print_version(stderr); |
| if (gfp->num_channels==2 && gfp->stereo==1) { |
| fprintf(stderr, "Autoconverting from stereo to mono. Setting encoding to mono mode.\n"); |
| } |
| if (gfp->resample_ratio!=1) { |
| fprintf(stderr,"Resampling: input=%ikHz output=%ikHz\n", |
| (int)in_samplerate,(int)out_samplerate); |
| } |
| if (gfp->highpass2>0.0) |
| fprintf(stderr, "Using polyphase highpass filter, transition band: %.0f Hz - %.0f Hz\n", |
| gfp->highpass1*out_samplerate*500, |
| gfp->highpass2*out_samplerate*500); |
| if (gfp->lowpass1>0.0) |
| fprintf(stderr, "Using polyphase lowpass filter, transition band: %.0f Hz - %.0f Hz\n", |
| gfp->lowpass1*out_samplerate*500, |
| gfp->lowpass2*out_samplerate*500); |
| |
| if (gfp->gtkflag) { |
| fprintf(stderr, "Analyzing %s \n",gfp->inPath); |
| } |
| else { |
| fprintf(stderr, "Encoding %s to %s\n", |
| (strcmp(gfp->inPath, "-")? mybasename(gfp->inPath) : "stdin"), |
| (strcmp(gfp->outPath, "-")? mybasename(gfp->outPath) : "stdout")); |
| if (gfp->VBR) |
| fprintf(stderr, "Encoding as %.1fkHz VBR(q=%i) %s MPEG%i LayerIII qval=%i\n", |
| gfp->out_samplerate/1000.0, |
| gfp->VBR_q,mode_names[gfp->mode],2-gfp->version,gfp->quality); |
| else |
| fprintf(stderr, "Encoding as %.1f kHz %d kbps %s MPEG%i LayerIII (%4.1fx) qval=%i\n", |
| gfp->out_samplerate/1000.0,gfp->brate, |
| mode_names[gfp->mode],2-gfp->version,compression,gfp->quality); |
| } |
| fflush(stderr); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| /************************************************************************ |
| * |
| * 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 day, 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 |
| |
| */ |
| int lame_encode_frame(lame_global_flags *gfp, |
| short int inbuf_l[],short int inbuf_r[], |
| int mf_size,char *mp3buf, int mp3buf_size) |
| { |
| static unsigned long frameBits; |
| static unsigned long bitsPerSlot; |
| static FLOAT8 frac_SpF; |
| static FLOAT8 slot_lag; |
| static unsigned long sentBits = 0; |
| FLOAT8 xr[2][2][576]; |
| int l3_enc[2][2][576]; |
| int mp3count; |
| III_psy_ratio masking_ratio[2][2]; /*LR ratios */ |
| III_psy_ratio masking_MS_ratio[2][2]; /*MS ratios */ |
| III_psy_ratio (*masking)[2][2]; /*LR ratios and MS ratios*/ |
| III_scalefac_t scalefac[2][2]; |
| short int *inbuf[2]; |
| |
| typedef FLOAT8 pedata[2][2]; |
| pedata pe,pe_MS; |
| pedata *pe_use; |
| |
| int ch,gr,mean_bits; |
| int bitsPerFrame; |
| |
| int check_ms_stereo; |
| static FLOAT8 ms_ratio[2]={0,0}; |
| FLOAT8 ms_ratio_next=0; |
| FLOAT8 ms_ratio_prev=0; |
| static FLOAT8 ms_ener_ratio[2]={0,0}; |
| |
| memset((char *) masking_ratio, 0, sizeof(masking_ratio)); |
| memset((char *) masking_MS_ratio, 0, sizeof(masking_MS_ratio)); |
| memset((char *) scalefac, 0, sizeof(scalefac)); |
| inbuf[0]=inbuf_l; |
| inbuf[1]=inbuf_r; |
| |
| gfp->mode_ext = MPG_MD_LR_LR; |
| |
| if (gfp->frameNum==0 ) { |
| /* Figure average number of 'slots' per frame. */ |
| FLOAT8 avg_slots_per_frame; |
| FLOAT8 sampfreq = gfp->out_samplerate/1000.0; |
| int bit_rate = gfp->brate; |
| sentBits = 0; |
| bitsPerSlot = 8; |
| avg_slots_per_frame = (bit_rate*gfp->framesize) / |
| (sampfreq* bitsPerSlot); |
| /* -f fast-math option causes some strange rounding here, be carefull: */ |
| frac_SpF = avg_slots_per_frame - floor(avg_slots_per_frame + 1e-9); |
| if (fabs(frac_SpF) < 1e-9) frac_SpF = 0; |
| |
| slot_lag = -frac_SpF; |
| gfp->padding = 1; |
| if (frac_SpF==0) gfp->padding = 0; |
| /* check FFT will not use a negative starting offset */ |
| assert(576>=FFTOFFSET); |
| /* check if we have enough data for FFT */ |
| assert(mf_size>=(BLKSIZE+gfp->framesize-FFTOFFSET)); |
| } |
| |
| |
| /********************** padding *****************************/ |
| switch (gfp->padding_type) { |
| case 0: |
| gfp->padding=0; |
| break; |
| case 1: |
| gfp->padding=1; |
| break; |
| case 2: |
| default: |
| if (gfp->VBR) { |
| gfp->padding=0; |
| } else { |
| if (gfp->disable_reservoir) { |
| gfp->padding = 0; |
| /* if the user specified --nores, dont very gfp->padding either */ |
| /* tiny changes in frac_SpF rounding will cause file differences */ |
| }else{ |
| if (frac_SpF != 0) { |
| if (slot_lag > (frac_SpF-1.0) ) { |
| slot_lag -= frac_SpF; |
| gfp->padding = 0; |
| } |
| else { |
| gfp->padding = 1; |
| slot_lag += (1-frac_SpF); |
| } |
| } |
| } |
| } |
| } |
| |
| |
| /********************** status display *****************************/ |
| if (!gfp->gtkflag && !gfp->silent) { |
| int mod = gfp->version == 0 ? 200 : 50; |
| if (gfp->frameNum%mod==0) { |
| timestatus(gfp->out_samplerate,gfp->frameNum,gfp->totalframes,gfp->framesize); |
| #ifdef BRHIST |
| if (disp_brhist) |
| { |
| brhist_add_count(); |
| brhist_disp(); |
| } |
| #endif |
| } |
| } |
| |
| |
| if (gfp->psymodel) { |
| /* psychoacoustic model |
| * psy model has a 1 granule (576) delay that we must compensate for |
| * (mt 6/99). |
| */ |
| short int *bufp[2]; /* address of beginning of left & right granule */ |
| int blocktype[2]; |
| |
| ms_ratio_prev=ms_ratio[gfp->mode_gr-1]; |
| for (gr=0; gr < gfp->mode_gr ; gr++) { |
| |
| for ( ch = 0; ch < gfp->stereo; ch++ ) |
| bufp[ch] = &inbuf[ch][576 + gr*576-FFTOFFSET]; |
| |
| L3psycho_anal( gfp,bufp, gr, |
| &ms_ratio[gr],&ms_ratio_next,&ms_ener_ratio[gr], |
| masking_ratio, masking_MS_ratio, |
| pe[gr],pe_MS[gr],blocktype); |
| |
| for ( ch = 0; ch < gfp->stereo; ch++ ) |
| l3_side.gr[gr].ch[ch].tt.block_type=blocktype[ch]; |
| |
| } |
| }else{ |
| for (gr=0; gr < gfp->mode_gr ; gr++) |
| for ( ch = 0; ch < gfp->stereo; ch++ ) { |
| l3_side.gr[gr].ch[ch].tt.block_type=NORM_TYPE; |
| pe[gr][ch]=700; |
| } |
| } |
| |
| |
| /* block type flags */ |
| for( gr = 0; gr < gfp->mode_gr; gr++ ) { |
| for ( ch = 0; ch < gfp->stereo; ch++ ) { |
| gr_info *cod_info = &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(gfp,inbuf[0], inbuf[1], xr, &l3_side); |
| |
| /* use m/s gfp->stereo? */ |
| check_ms_stereo = (gfp->mode == MPG_MD_JOINT_STEREO); |
| if (check_ms_stereo) { |
| /* make sure block type is the same in each channel */ |
| check_ms_stereo = |
| (l3_side.gr[0].ch[0].tt.block_type==l3_side.gr[0].ch[1].tt.block_type) && |
| (l3_side.gr[1].ch[0].tt.block_type==l3_side.gr[1].ch[1].tt.block_type); |
| } |
| if (check_ms_stereo) { |
| /* ms_ratio = is like the ratio of side_energy/total_energy */ |
| FLOAT8 ms_ratio_ave,ms_ener_ratio_ave; |
| /* ms_ratio_ave = .5*(ms_ratio[0] + ms_ratio[1]);*/ |
| ms_ratio_ave = .25*(ms_ratio[0] + ms_ratio[1]+ |
| ms_ratio_prev + ms_ratio_next); |
| ms_ener_ratio_ave = .5*(ms_ener_ratio[0]+ms_ener_ratio[1]); |
| if ( ms_ratio_ave <.35 /*&& ms_ener_ratio_ave<.75*/ ) gfp->mode_ext = MPG_MD_MS_LR; |
| } |
| if (gfp->force_ms) gfp->mode_ext = MPG_MD_MS_LR; |
| |
| |
| #ifdef HAVEGTK |
| if (gfp->gtkflag) { |
| int j; |
| for ( gr = 0; gr < gfp->mode_gr; gr++ ) { |
| for ( ch = 0; ch < gfp->stereo; ch++ ) { |
| pinfo->ms_ratio[gr]=ms_ratio[gr]; |
| pinfo->ms_ener_ratio[gr]=ms_ener_ratio[gr]; |
| pinfo->blocktype[gr][ch]= |
| l3_side.gr[gr].ch[ch].tt.block_type; |
| for ( j = 0; j < 576; j++ ) pinfo->xr[gr][ch][j]=xr[gr][ch][j]; |
| /* if MS stereo, switch to MS psy data */ |
| if (gfp->mode_ext==MPG_MD_MS_LR) { |
| pinfo->pe[gr][ch]=pinfo->pe[gr][ch+2]; |
| pinfo->ers[gr][ch]=pinfo->ers[gr][ch+2]; |
| memcpy(pinfo->energy[gr][ch],pinfo->energy[gr][ch+2], |
| sizeof(pinfo->energy[gr][ch])); |
| } |
| } |
| } |
| } |
| #endif |
| |
| |
| |
| |
| /* bit and noise allocation */ |
| if (MPG_MD_MS_LR == gfp->mode_ext) { |
| masking = &masking_MS_ratio; /* use MS masking */ |
| pe_use=&pe_MS; |
| } else { |
| masking = &masking_ratio; /* use LR masking */ |
| pe_use=&pe; |
| } |
| |
| |
| /* |
| VBR_iteration_loop_new( gfp,*pe_use, ms_ratio, xr, masking, &l3_side, l3_enc, |
| &scalefac); |
| */ |
| |
| |
| if (gfp->VBR) { |
| VBR_iteration_loop( gfp,*pe_use, ms_ratio, xr, *masking, &l3_side, l3_enc, |
| scalefac); |
| }else{ |
| iteration_loop( gfp,*pe_use, ms_ratio, xr, *masking, &l3_side, l3_enc, |
| scalefac); |
| } |
| |
| |
| |
| |
| #ifdef BRHIST |
| brhist_temp[gfp->bitrate_index]++; |
| #endif |
| |
| |
| /* write the frame to the bitstream */ |
| getframebits(gfp,&bitsPerFrame,&mean_bits); |
| III_format_bitstream( gfp,bitsPerFrame, l3_enc, &l3_side, |
| scalefac, &bs); |
| |
| |
| frameBits = bs.totbit - sentBits; |
| |
| |
| if ( frameBits % bitsPerSlot ) /* a program failure */ |
| fprintf( stderr, "Sent %ld bits = %ld slots plus %ld\n", |
| frameBits, frameBits/bitsPerSlot, |
| frameBits%bitsPerSlot ); |
| sentBits += frameBits; |
| |
| /* copy mp3 bit buffer into array */ |
| mp3count = copy_buffer(mp3buf,mp3buf_size,&bs); |
| |
| if (gfp->bWriteVbrTag) AddVbrFrame((int)(sentBits/8)); |
| |
| #ifdef HAVEGTK |
| if (gfp->gtkflag) { |
| int j; |
| for ( ch = 0; ch < gfp->stereo; ch++ ) { |
| for ( j = 0; j < FFTOFFSET; j++ ) |
| pinfo->pcmdata[ch][j] = pinfo->pcmdata[ch][j+gfp->framesize]; |
| for ( j = FFTOFFSET; j < 1600; j++ ) { |
| pinfo->pcmdata[ch][j] = inbuf[ch][j-FFTOFFSET]; |
| } |
| } |
| } |
| #endif |
| gfp->frameNum++; |
| |
| return mp3count; |
| } |
| |
| |
| |
| int fill_buffer_resample(lame_global_flags *gfp,short int *outbuf,int desired_len, |
| short int *inbuf,int len,int *num_used,int ch) { |
| |
| static FLOAT8 itime[2]; |
| #define OLDBUFSIZE 5 |
| static short int inbuf_old[2][OLDBUFSIZE]; |
| static int init[2]={0,0}; |
| int i,j=0,k,linear,value; |
| |
| if (gfp->frameNum==0 && !init[ch]) { |
| init[ch]=1; |
| itime[ch]=0; |
| memset((char *) inbuf_old[ch], 0, sizeof(short int)*OLDBUFSIZE); |
| } |
| if (gfp->frameNum!=0) init[ch]=0; /* reset, for next time framenum=0 */ |
| |
| |
| /* if downsampling by an integer multiple, use linear resampling, |
| * otherwise use quadratic */ |
| linear = ( fabs(gfp->resample_ratio - floor(.5+gfp->resample_ratio)) < .0001 ); |
| |
| /* time of j'th element in inbuf = itime + j/ifreq; */ |
| /* time of k'th element in outbuf = j/ofreq */ |
| for (k=0;k<desired_len;k++) { |
| int y0,y1,y2,y3; |
| FLOAT8 x0,x1,x2,x3; |
| FLOAT8 time0; |
| |
| time0 = k*gfp->resample_ratio; /* time of k'th output sample */ |
| j = floor( time0 -itime[ch] ); |
| /* itime[ch] + j; */ /* time of j'th input sample */ |
| if (j+2 >= len) break; /* not enough data in input buffer */ |
| |
| x1 = time0-(itime[ch]+j); |
| x2 = x1-1; |
| y1 = (j<0) ? inbuf_old[ch][OLDBUFSIZE+j] : inbuf[j]; |
| y2 = ((1+j)<0) ? inbuf_old[ch][OLDBUFSIZE+1+j] : inbuf[1+j]; |
| |
| /* linear resample */ |
| if (linear) { |
| outbuf[k] = floor(.5 + (y2*x1-y1*x2) ); |
| } else { |
| /* quadratic */ |
| x0 = x1+1; |
| x3 = x1-2; |
| y0 = ((j-1)<0) ? inbuf_old[ch][OLDBUFSIZE+(j-1)] : inbuf[j-1]; |
| y3 = ((j+2)<0) ? inbuf_old[ch][OLDBUFSIZE+(j+2)] : inbuf[j+2]; |
| value = floor(.5 + |
| -y0*x1*x2*x3/6 + y1*x0*x2*x3/2 - y2*x0*x1*x3/2 +y3*x0*x1*x2/6 |
| ); |
| if (value > 32767) outbuf[k]=32767; |
| else if (value < -32767) outbuf[k]=-32767; |
| else outbuf[k]=value; |
| |
| /* |
| printf("k=%i new=%i [ %i %i %i %i ]\n",k,outbuf[k], |
| y0,y1,y2,y3); |
| */ |
| } |
| } |
| |
| |
| /* k = number of samples added to outbuf */ |
| /* last k sample used data from j,j+1, or j+1 overflowed buffer */ |
| /* remove num_used samples from inbuf: */ |
| *num_used = Min(len,j+2); |
| itime[ch] += *num_used - k*gfp->resample_ratio; |
| for (i=0;i<OLDBUFSIZE;i++) |
| inbuf_old[ch][i]=inbuf[*num_used + i -OLDBUFSIZE]; |
| return k; |
| } |
| |
| |
| |
| |
| int fill_buffer(lame_global_flags *gfp,short int *outbuf,int desired_len,short int *inbuf,int len) { |
| int j; |
| j=Min(desired_len,len); |
| memcpy( (char *) outbuf,(char *)inbuf,sizeof(short int)*j); |
| return j; |
| } |
| |
| |
| |
| |
| /* |
| * 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(lame_global_flags *gfp, |
| short int buffer_l[], short int buffer_r[],int nsamples, |
| char *mp3buf, int mp3buf_size) |
| { |
| static int frame_buffered=0; |
| int mp3size=0,ret,i,ch,mf_needed; |
| |
| short int *in_buffer[2]; |
| in_buffer[0] = buffer_l; |
| in_buffer[1] = buffer_r; |
| |
| /* some sanity checks */ |
| assert(ENCDELAY>=MDCTDELAY); |
| assert(BLKSIZE-FFTOFFSET >= 0); |
| mf_needed = BLKSIZE+gfp->framesize-FFTOFFSET; |
| assert(MFSIZE>=mf_needed); |
| |
| /* The reason for |
| * int mf_samples_to_encode = ENCDELAY + 288; |
| * ENCDELAY = internal encoder delay. And then we have to add 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. |
| */ |
| if (gfp->frameNum==0 && !frame_buffered) { |
| memset((char *) mfbuf, 0, sizeof(mfbuf)); |
| frame_buffered=1; |
| mf_samples_to_encode = ENCDELAY+288; |
| mf_size=ENCDELAY-MDCTDELAY; /* we pad input with this many 0's */ |
| } |
| if (gfp->frameNum==1) { |
| /* reset, for the next time frameNum==0 */ |
| frame_buffered=0; |
| } |
| |
| if (gfp->num_channels==2 && gfp->stereo==1) { |
| /* downsample to mono */ |
| for (i=0; i<nsamples; ++i) { |
| in_buffer[0][i]=((int)in_buffer[0][i]+(int)in_buffer[1][i])/2; |
| in_buffer[1][i]=0; |
| } |
| } |
| |
| |
| while (nsamples > 0) { |
| int n_in=0; |
| int n_out=0; |
| /* copy in new samples */ |
| for (ch=0; ch<gfp->stereo; ch++) { |
| if (gfp->resample_ratio!=1) { |
| n_out=fill_buffer_resample(gfp,&mfbuf[ch][mf_size],gfp->framesize, |
| in_buffer[ch],nsamples,&n_in,ch); |
| } else { |
| n_out=fill_buffer(gfp,&mfbuf[ch][mf_size],gfp->framesize,in_buffer[ch],nsamples); |
| n_in = n_out; |
| } |
| in_buffer[ch] += n_in; |
| } |
| |
| |
| nsamples -= n_in; |
| mf_size += n_out; |
| assert(mf_size<=MFSIZE); |
| mf_samples_to_encode += n_out; |
| |
| if (mf_size >= mf_needed) { |
| /* encode the frame */ |
| ret = lame_encode_frame(gfp,mfbuf[0],mfbuf[1],mf_size,mp3buf,mp3buf_size); |
| if (ret == -1) { |
| /* fatel error: mp3buffer was too small */ |
| return -1; |
| } |
| mp3buf += ret; |
| mp3size += ret; |
| |
| /* shift out old samples */ |
| mf_size -= gfp->framesize; |
| mf_samples_to_encode -= gfp->framesize; |
| for (ch=0; ch<gfp->stereo; ch++) |
| for (i=0; i<mf_size; i++) |
| mfbuf[ch][i]=mfbuf[ch][i+gfp->framesize]; |
| } |
| } |
| assert(nsamples==0); |
| return mp3size; |
| } |
| |
| |
| |
| |
| int lame_encode_buffer_interleaved(lame_global_flags *gfp, |
| short int buffer[], int nsamples, char *mp3buf, int mp3buf_size) |
| { |
| static int frame_buffered=0; |
| int mp3size=0,ret,i,ch,mf_needed; |
| |
| /* some sanity checks */ |
| assert(ENCDELAY>=MDCTDELAY); |
| assert(BLKSIZE-FFTOFFSET >= 0); |
| mf_needed = BLKSIZE+gfp->framesize-FFTOFFSET; |
| assert(MFSIZE>=mf_needed); |
| |
| if (gfp->num_channels == 1) { |
| return lame_encode_buffer(gfp,buffer, NULL ,nsamples,mp3buf,mp3buf_size); |
| } |
| |
| if (gfp->resample_ratio!=1) { |
| 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 -1; |
| } |
| 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; |
| } |
| |
| |
| if (gfp->frameNum==0 && !frame_buffered) { |
| memset((char *) mfbuf, 0, sizeof(mfbuf)); |
| frame_buffered=1; |
| mf_samples_to_encode = ENCDELAY+288; |
| mf_size=ENCDELAY-MDCTDELAY; /* we pad input with this many 0's */ |
| } |
| if (gfp->frameNum==1) { |
| /* reset, for the next time frameNum==0 */ |
| frame_buffered=0; |
| } |
| |
| if (gfp->num_channels==2 && gfp->stereo==1) { |
| /* downsample to mono */ |
| for (i=0; i<nsamples; ++i) { |
| buffer[2*i]=((int)buffer[2*i]+(int)buffer[2*i+1])/2; |
| buffer[2*i+1]=0; |
| } |
| } |
| |
| |
| while (nsamples > 0) { |
| int n_out; |
| /* copy in new samples */ |
| n_out = Min(gfp->framesize,nsamples); |
| for (i=0; i<n_out; ++i) { |
| mfbuf[0][mf_size+i]=buffer[2*i]; |
| mfbuf[1][mf_size+i]=buffer[2*i+1]; |
| } |
| buffer += 2*n_out; |
| |
| nsamples -= n_out; |
| mf_size += n_out; |
| assert(mf_size<=MFSIZE); |
| mf_samples_to_encode += n_out; |
| |
| if (mf_size >= mf_needed) { |
| /* encode the frame */ |
| ret = lame_encode_frame(gfp,mfbuf[0],mfbuf[1],mf_size,mp3buf,mp3buf_size); |
| if (ret == -1) { |
| /* fatel error: mp3buffer was too small */ |
| return -1; |
| } |
| mp3buf += ret; |
| mp3size += ret; |
| |
| /* shift out old samples */ |
| mf_size -= gfp->framesize; |
| mf_samples_to_encode -= gfp->framesize; |
| for (ch=0; ch<gfp->stereo; ch++) |
| for (i=0; i<mf_size; i++) |
| mfbuf[ch][i]=mfbuf[ch][i+gfp->framesize]; |
| } |
| } |
| assert(nsamples==0); |
| return mp3size; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| /* old LAME interface */ |
| /* With this interface, it is the users responsibilty to keep track of the |
| * buffered, unencoded samples. Thus mf_samples_to_encode is not incremented. |
| * |
| * lame_encode() is also used to flush the PCM input buffer by |
| * lame_encode_finish() |
| */ |
| int lame_encode(lame_global_flags *gfp, short int in_buffer[2][1152],char *mp3buf,int size){ |
| int imp3,save; |
| save = mf_samples_to_encode; |
| imp3= lame_encode_buffer(gfp,in_buffer[0],in_buffer[1],576*gfp->mode_gr, |
| mp3buf,size); |
| mf_samples_to_encode = save; |
| return imp3; |
| } |
| |
| |
| #ifdef __FreeBSD__ |
| # include <floatingpoint.h> |
| #endif |
| |
| |
| /* initialize mp3 encoder */ |
| void lame_init(lame_global_flags *gfp) |
| { |
| |
| /* |
| * Disable floating point exceptions |
| */ |
| #if defined(__FreeBSD__) && defined(FP_X_INV) && defined(FP_X_DZ) |
| { |
| /* 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)); |
| /* fprintf(stderr,"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) && !defined(__riscos__) |
| #if defined(_MSC_VER) |
| { |
| #include <float.h> |
| 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 0x00000001 /* inexact (precision) */ |
| # define _EM_UNDERFLOW 0x00000002 /* underflow */ |
| # define _EM_OVERFLOW 0x00000004 /* overflow */ |
| # define _EM_ZERODIVIDE 0x00000008 /* zero divide */ |
| # define _EM_INVALID 0x00000010 /* invalid */ |
| { |
| unsigned int mask; |
| _FPU_GETCW(mask); |
| /* Set the FPU control word to abort on most FPEs */ |
| mask &= ~(_EM_UNDERFLOW | _EM_OVERFLOW | _EM_ZERODIVIDE | _EM_INVALID); |
| _FPU_SETCW(mask); |
| } |
| # else |
| { |
| # include <fpu_control.h> |
| #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 |
| unsigned int mask; |
| _FPU_GETCW(mask); |
| /* 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 );*/ |
| mask &= ~( _FPU_MASK_IM | _FPU_MASK_ZM | _FPU_MASK_OM ); |
| _FPU_SETCW(mask); |
| } |
| #endif |
| #endif /* ABORTFP && !__riscos__ */ |
| |
| |
| |
| /* Global flags. set defaults here */ |
| gfp->allow_diff_short=0; |
| gfp->ATHonly=0; |
| gfp->noATH=0; |
| gfp->bWriteVbrTag=1; |
| gfp->cwlimit=0; |
| gfp->disable_reservoir=0; |
| gfp->experimentalX = 0; |
| gfp->experimentalY = 0; |
| gfp->experimentalZ = 0; |
| gfp->frameNum=0; |
| gfp->gtkflag=0; |
| gfp->quality=5; |
| gfp->input_format=sf_unknown; |
| |
| gfp->filter_type=0; |
| gfp->lowpassfreq=0; |
| gfp->highpassfreq=0; |
| gfp->lowpasswidth=-1; |
| gfp->highpasswidth=-1; |
| gfp->lowpass1=0; |
| gfp->lowpass2=0; |
| gfp->highpass1=0; |
| gfp->highpass2=0; |
| gfp->lowpass_band=32; |
| gfp->highpass_band=-1; |
| |
| gfp->no_short_blocks=0; |
| gfp->resample_ratio=1; |
| gfp->padding_type=2; |
| gfp->padding=0; |
| gfp->swapbytes=0; |
| gfp->silent=0; |
| gfp->totalframes=0; |
| gfp->VBR=0; |
| gfp->VBR_q=4; |
| gfp->VBR_min_bitrate_kbps=0; |
| gfp->VBR_max_bitrate_kbps=0; |
| gfp->VBR_min_bitrate=1; |
| gfp->VBR_max_bitrate=13; |
| |
| |
| gfp->version = 1; /* =1 Default: MPEG-1 */ |
| gfp->mode = MPG_MD_JOINT_STEREO; |
| gfp->mode_fixed=0; |
| gfp->force_ms=0; |
| gfp->brate=0; |
| gfp->copyright=0; |
| gfp->original=1; |
| gfp->extension=0; |
| gfp->error_protection=0; |
| gfp->emphasis=0; |
| gfp->in_samplerate=1000*44.1; |
| gfp->out_samplerate=0; |
| gfp->num_channels=2; |
| gfp->num_samples=MAX_U_32_NUM; |
| |
| gfp->inPath=NULL; |
| gfp->outPath=NULL; |
| id3tag.used=0; |
| |
| } |
| |
| |
| |
| /*****************************************************************/ |
| /* flush internal mp3 buffers, */ |
| /*****************************************************************/ |
| int lame_encode_finish(lame_global_flags *gfp,char *mp3buffer, int mp3buffer_size) |
| { |
| int imp3,mp3count,mp3buffer_size_remaining; |
| short int buffer[2][1152]; |
| memset((char *)buffer,0,sizeof(buffer)); |
| mp3count = 0; |
| |
| while (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; |
| imp3=lame_encode(gfp,buffer,mp3buffer,mp3buffer_size_remaining); |
| |
| if (imp3 == -1) { |
| /* fatel error: mp3buffer too small */ |
| desalloc_buffer(&bs); /* Deallocate all buffers */ |
| return -1; |
| } |
| mp3buffer += imp3; |
| mp3count += imp3; |
| mf_samples_to_encode -= gfp->framesize; |
| } |
| |
| |
| gfp->frameNum--; |
| if (!gfp->gtkflag && !gfp->silent) { |
| timestatus(gfp->out_samplerate,gfp->frameNum,gfp->totalframes,gfp->framesize); |
| #ifdef BRHIST |
| if (disp_brhist) |
| { |
| brhist_add_count(); |
| brhist_disp(); |
| brhist_disp_total(gfp); |
| } |
| #endif |
| fprintf(stderr,"\n"); |
| fflush(stderr); |
| } |
| |
| |
| III_FlushBitstream(); |
| mp3buffer_size_remaining = mp3buffer_size - mp3count; |
| /* if user specifed buffer size = 0, dont check size */ |
| if (mp3buffer_size == 0) mp3buffer_size_remaining=0; |
| |
| imp3= copy_buffer(mp3buffer,mp3buffer_size_remaining,&bs); |
| if (imp3 == -1) { |
| /* fatel error: mp3buffer too small */ |
| desalloc_buffer(&bs); /* Deallocate all buffers */ |
| return -1; |
| } |
| |
| mp3count += imp3; |
| desalloc_buffer(&bs); /* Deallocate all buffers */ |
| return mp3count; |
| } |
| |
| |
| /*****************************************************************/ |
| /* write VBR Xing header, and ID3 tag, if asked for */ |
| /*****************************************************************/ |
| void lame_mp3_tags(lame_global_flags *gfp) |
| { |
| if (gfp->bWriteVbrTag) |
| { |
| /* Calculate relative quality of VBR stream |
| * 0=best, 100=worst */ |
| int nQuality=gfp->VBR_q*100/9; |
| /* Write Xing header again */ |
| PutVbrTag(gfp->outPath,nQuality,1-gfp->version); |
| } |
| |
| |
| /* write an ID3 tag */ |
| if(id3tag.used) { |
| id3_buildtag(&id3tag); |
| id3_writetag(gfp->outPath, &id3tag); |
| } |
| } |
| |
| |
| void lame_version(lame_global_flags *gfp,char *ostring) { |
| strncpy(ostring,get_lame_version(),20); |
| } |
| |