out_lame.cpp Source File

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.2 2004/01/24 17:22:52 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   Shouter *ice = (Shouter*)icelist.begin();
    00142   while(ice) {
    00143     ice->bps( bps() );
    00144     ice = (Shouter*)ice->next;
    00145   }
    00146
    00147   lame_set_out_samplerate(enc_flags,freq());
    00148
    00149   /* CHANNELS
    00150      mode 2 (double channel) is unsupported */
    00151   int mode;
    00152   switch( channels() ) {
    00153     /* 0,1,2,3 stereo,jstereo,dual channel,mono */
    00154   case 1: mode = 3; break;
    00155   case 2: mode = 1; break;
    00156   default: mode = 3; break;
    00157   }
    00158   lame_set_mode(enc_flags,(MPEG_mode_e)mode);
    00159
    00160
    00161   /* in case of VBR
    00162   func("reversed quality is %i, guessed bps %i",(int)fabs( 10 - quality()),bps());
    00163   lame_set_VBR_q(enc_flags,(int)fabs( 10 - quality() ));
    00164   lame_set_VBR_mean_bitrate_kbps(enc_flags,bps());
    00165   */
    00166
    00167   /* lame chooses for us frequency filtering when values are 0 */
    00168   lame_set_lowpassfreq(enc_flags,lowpass());
    00169   lame_set_highpassfreq(enc_flags,highpass());
    00170
    00171   int res = lame_init_params(enc_flags);
    00172   if(res<0) {
    00173     error("lame_init_params failed");
    00174     lame_close(enc_flags);
    00175     enc_flags = NULL;
    00176   }
    00177
    00178   return (res<0)?false:true;
    00179
    00180 }
    00181
    00182 OutLame::~OutLame() {
    00183   func("OutLame::~OutLame() %p",this);
    00184   act("closing lame encoder");
    00185   //  if(running) flush();
    00186   if(enc_flags) lame_close(enc_flags);
    00187 }
    00188
    00189 #endif