Main Page   Modules   Class Hierarchy   Compound List   File List   Compound Members   File Members  

out_lame.cpp

00001 /* MuSE - Multiple Streaming Engine
00002  * Copyright (C) 2000-2002 Denis Rojo aka jaromil <jaromil@dyne.org>
00003  *
00004  * This source code is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Public License as published 
00006  * by the Free Software Foundation; either version 2 of the License,
00007  * or (at your option) any later version.
00008  *
00009  * This source code is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00012  * Please refer to the GNU Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Public License along with
00015  * this source code; if not, write to:
00016  * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  *
00018  * "$Id: out_lame.cpp,v 1.4 2004/12/15 18:18:06 jaromil Exp $"
00019  *
00020  */
00021 
00022 #include <math.h>
00023 #include <out_lame.h>
00024 #ifdef HAVE_LAME
00025 
00026 #include <jutils.h>
00027 #include <generic.h>
00028 #include <config.h>
00029 
00030 /* I think a tighter bound could be:  (mt, March 2000)
00031  * MPEG1:
00032  *    num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512
00033  * MPEG2:
00034  *    num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256
00035  */
00036 
00037 /* mp3 encoder */
00038 
00039 OutLame::OutLame() 
00040   : OutChannel("lame") {
00041   func("OutLame::OutLame()");
00042   
00043   sprintf(name,"Lame MP3 encoder");
00044   sprintf(version,"version %s",get_lame_version());
00045 
00046   tipo = MP3;
00047   enc_flags = NULL;
00048 
00049 }
00050 
00051 /* note: num is number of samples in the L (or R) channel
00052    not the total number of samples in pcm[] */
00053 int OutLame::encode() {    
00054   int num, smp;
00055 
00056   /* num is number of bytes read from pipe
00057      sound in pipe is always 16bit stereo ... */
00058   num = erbapipa->read(OUT_CHUNK<<2,pcm);
00059   if(num<0) return num;
00060   /* ... therefore samples are num/4 */
00061   smp = num>>2;
00062 
00063   if(!enc_flags) {
00064     error("Lame encoder is not initialized");
00065     return -5;
00066   }
00067 
00068   encoded = 
00069     lame_encode_buffer_interleaved
00070     (enc_flags, pcm, smp, (unsigned char *)buffer, 0); //ENCBUFFER_SIZE);
00071   
00072   if(encoded<0)
00073     switch(encoded) {
00074     case -1:
00075       error("lame encoder: mp3 buffer is too small");
00076       break;
00077     case -2:
00078       error("lame encoder: malloc() problem");
00079       break;
00080     case -3:
00081       error("lame encoder: lame_init_params() not called");
00082       break;
00083     case -4:
00084       error("lame encoder: psycho acoustic problems (yes, shamanic indeed)");
00085       break;
00086     default:
00087       error("lame encoder: internal error");
00088       break;
00089     }
00090   
00091   return encoded;
00092 }
00093 
00094 void OutLame::flush() {
00095   if(!enc_flags) {
00096     error("Lame encoder is not initialized");
00097     return;
00098   }
00099   lock();
00100   encoded = lame_encode_flush_nogap
00101     (enc_flags,(unsigned char*)buffer,ENCBUFFER_SIZE);
00102   shout();
00103   unlock();
00104 }
00105 
00106 bool OutLame::init() {
00107   func("initializing %s %s",name,version);
00108 
00109   if(!apply_profile()) {
00110     error("problems in setting up codec parameters");
00111     lame_close(enc_flags);
00112     enc_flags = NULL;
00113     return false;
00114   }
00115 
00116   initialized = true;
00117   return initialized;
00118 }
00119 
00120 bool OutLame::apply_profile() {
00121 
00122 
00123   if(enc_flags) lame_close(enc_flags);
00124   enc_flags = lame_init();
00125 
00126   lame_set_errorf(enc_flags,(void (*)(const char*, va_list))error);
00127   lame_set_debugf(enc_flags,(void (*)(const char*, va_list))func);
00128   lame_set_msgf(enc_flags,(void (*)(const char*, va_list))act);
00129   
00130   lame_set_num_samples(enc_flags,OUT_CHUNK);
00131   lame_set_num_channels(enc_flags,2); // the mixed input stream is stereo
00132   lame_set_in_samplerate(enc_flags,SAMPLE_RATE); // the mixed input stream is 44khz
00133   lame_set_error_protection(enc_flags,1); // 2 bytes per frame for a CRC checksum
00134   lame_set_compression_ratio(enc_flags,0);
00135   lame_set_quality(enc_flags,2); // 1..9 1=best 9=worst (suggested: 2, 5, 7)
00136   //  lame_set_VBR(enc_flags,vbr_abr);
00137 
00138 
00139   /* BITRATE */
00140   lame_set_brate(enc_flags,bps());
00141 
00142   Shouter *ice = (Shouter*)icelist.begin();
00143   while(ice) {
00144     char tmp[256];
00145 
00146     snprintf(tmp,256,"%u",bps());       ice->bps( tmp );
00147     snprintf(tmp,256,"%u",freq());      ice->freq( tmp );
00148     snprintf(tmp,256,"%u",channels());  ice->channels( tmp );
00149     
00150     ice = (Shouter*)ice->next;
00151   }
00152 
00153   lame_set_out_samplerate(enc_flags,freq());
00154 
00155   /* CHANNELS
00156      mode 2 (double channel) is unsupported */
00157   int mode;
00158   switch( channels() ) {
00159     /* 0,1,2,3 stereo,jstereo,dual channel,mono */
00160   case 1: mode = 3; break;
00161   case 2: mode = 1; break;
00162   default: mode = 3; break;
00163   }
00164   lame_set_mode(enc_flags,(MPEG_mode_e)mode);
00165 
00166 
00167   /* in case of VBR 
00168   func("reversed quality is %i, guessed bps %i",(int)fabs( 10 - quality()),bps());
00169   lame_set_VBR_q(enc_flags,(int)fabs( 10 - quality() ));
00170   lame_set_VBR_mean_bitrate_kbps(enc_flags,bps());
00171   */
00172 
00173   /* lame chooses for us frequency filtering when values are 0 */
00174   lame_set_lowpassfreq(enc_flags,lowpass());
00175   lame_set_highpassfreq(enc_flags,highpass());  
00176   
00177   int res = lame_init_params(enc_flags);
00178   if(res<0) {
00179     error("lame_init_params failed");
00180     lame_close(enc_flags);
00181     enc_flags = NULL;
00182   }
00183 
00184   return (res<0)?false:true;
00185 
00186 }
00187 
00188 OutLame::~OutLame() {
00189   func("OutLame::~OutLame() %p",this);
00190   act("closing lame encoder");
00191   //  if(running) flush();
00192   if(enc_flags) lame_close(enc_flags);
00193 }
00194 
00195 #endif

Generated on Thu Dec 16 12:28:21 2004 for MuSE by doxygen1.3