00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include "config.h"
00034 #endif
00035
00036
00037 #ifdef HAVE_LAME_LIB
00038
00039
00040
00041 #include "Exception.h"
00042 #include "Util.h"
00043 #include "LameLibEncoder.h"
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 static const char fileid[] = "$Id: LameLibEncoder.cpp,v 1.19 2005/04/13 19:04:55 jbebel Exp $";
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 bool
00066 LameLibEncoder :: open ( void )
00067 throw ( Exception )
00068 {
00069 if ( isOpen() ) {
00070 close();
00071 }
00072
00073
00074 if ( !sink->open() ) {
00075 throw Exception( __FILE__, __LINE__,
00076 "lame lib opening underlying sink error");
00077 }
00078
00079 lameGlobalFlags = lame_init();
00080
00081
00082 if ( !lameGlobalFlags || ((int)lameGlobalFlags) == -1 ) {
00083 throw Exception( __FILE__, __LINE__,
00084 "lame lib init error",
00085 (int) lameGlobalFlags);
00086 }
00087
00088 if ( 0 > lame_set_num_channels( lameGlobalFlags, getInChannel()) ) {
00089 throw Exception( __FILE__, __LINE__,
00090 "lame lib setting channels error",
00091 getInChannel() );
00092 }
00093
00094 if ( 0 > lame_set_mode( lameGlobalFlags,
00095 getOutChannel() == 1 ? MONO : JOINT_STEREO) ) {
00096 throw Exception( __FILE__, __LINE__,
00097 "lame lib setting mode error",
00098 JOINT_STEREO );
00099 }
00100
00101 reportEvent( 5, "set lame mode", lame_get_mode( lameGlobalFlags));
00102
00103 reportEvent( 5,
00104 "set lame channels",
00105 lame_get_num_channels( lameGlobalFlags));
00106
00107 if ( 0 > lame_set_in_samplerate( lameGlobalFlags, getInSampleRate()) ) {
00108 throw Exception( __FILE__, __LINE__,
00109 "lame lib setting input sample rate error",
00110 getInSampleRate() );
00111 }
00112
00113 reportEvent( 5,
00114 "set lame in sample rate",
00115 lame_get_in_samplerate( lameGlobalFlags));
00116
00117 if ( 0 > lame_set_out_samplerate( lameGlobalFlags, getOutSampleRate()) ) {
00118 throw Exception( __FILE__, __LINE__,
00119 "lame lib setting output sample rate error",
00120 getOutSampleRate() );
00121 }
00122
00123 reportEvent( 5,
00124 "set lame out sample rate",
00125 lame_get_out_samplerate( lameGlobalFlags));
00126
00127 switch ( getOutBitrateMode() ) {
00128
00129 case cbr: {
00130
00131 if ( 0 > lame_set_brate( lameGlobalFlags, getOutBitrate()) ) {
00132 throw Exception( __FILE__, __LINE__,
00133 "lame lib setting output bit rate error",
00134 getOutBitrate() );
00135 }
00136
00137 reportEvent( 5,
00138 "set lame bit rate",
00139 lame_get_brate( lameGlobalFlags));
00140
00141 double d = (1.0 - getOutQuality()) * 10.0;
00142
00143 if ( d > 9 ) {
00144 d = 9;
00145 }
00146
00147 int q = int (d);
00148
00149 if ( 0 > lame_set_quality( lameGlobalFlags, q) ) {
00150 throw Exception( __FILE__, __LINE__,
00151 "lame lib setting quality error", q);
00152 }
00153
00154 reportEvent( 5,
00155 "set lame quality",
00156 lame_get_quality( lameGlobalFlags));
00157 } break;
00158
00159 case abr:
00160
00161 if ( 0 > lame_set_VBR( lameGlobalFlags,vbr_abr)) {
00162 throw Exception( __FILE__, __LINE__,
00163 "lame lib setting abr error", vbr_abr);
00164 }
00165
00166 reportEvent( 5,
00167 "set lame abr bitrate",
00168 lame_get_VBR( lameGlobalFlags));
00169
00170 if ( 0 > lame_set_VBR_mean_bitrate_kbps( lameGlobalFlags,
00171 getOutBitrate())) {
00172 throw Exception( __FILE__, __LINE__,
00173 "lame lib setting abr mean bitrate error",
00174 getOutBitrate());
00175 }
00176
00177 reportEvent( 5,
00178 "set lame abr mean bitrate",
00179 lame_get_VBR_mean_bitrate_kbps( lameGlobalFlags));
00180 break;
00181
00182 case vbr: {
00183
00184 if ( 0 > lame_set_VBR( lameGlobalFlags, vbr_mtrh)) {
00185 throw Exception( __FILE__, __LINE__,
00186 "lame lib setting vbr error", vbr_mtrh );
00187 }
00188
00189 reportEvent( 5,
00190 "set lame vbr bitrate",
00191 lame_get_VBR( lameGlobalFlags));
00192
00193 double d = (1.0 - getOutQuality()) * 10.0;
00194
00195 if ( d > 9 ) {
00196 d = 9;
00197 }
00198
00199 int q = int (d);
00200
00201 if ( 0 > lame_set_VBR_q( lameGlobalFlags, q) ) {
00202 throw Exception( __FILE__, __LINE__,
00203 "lame lib setting vbr quality error", q);
00204 }
00205
00206 reportEvent( 5,
00207 "set lame vbr quality",
00208 lame_get_VBR_q( lameGlobalFlags));
00209 } break;
00210 }
00211
00212
00213 if ( 0 > lame_set_lowpassfreq( lameGlobalFlags, lowpass) ) {
00214 throw Exception( __FILE__, __LINE__,
00215 "lame lib setting lowpass frequency error",
00216 lowpass );
00217 }
00218
00219 reportEvent( 5,
00220 "set lame lowpass frequency",
00221 lame_get_lowpassfreq( lameGlobalFlags));
00222
00223 if ( 0 > lame_set_highpassfreq( lameGlobalFlags, highpass) ) {
00224 throw Exception( __FILE__, __LINE__,
00225 "lame lib setting highpass frequency error",
00226 lowpass );
00227 }
00228
00229 reportEvent( 5,
00230 "set lame highpass frequency",
00231 lame_get_highpassfreq( lameGlobalFlags));
00232
00233
00234
00235
00236
00237
00238 if ( 0 > lame_set_exp_nspsytune( lameGlobalFlags, 1) ) {
00239 throw Exception( __FILE__, __LINE__,
00240 "lame lib setting psycho acoustic model error");
00241 }
00242
00243 reportEvent( 5,
00244 "set lame psycho acoustic model",
00245 lame_get_exp_nspsytune( lameGlobalFlags));
00246
00247 if ( 0 > lame_set_error_protection( lameGlobalFlags, 1) ) {
00248 throw Exception( __FILE__, __LINE__,
00249 "lame lib setting error protection error",
00250 1 );
00251 }
00252
00253 reportEvent( 5,
00254 "set lame error protection",
00255 lame_get_error_protection( lameGlobalFlags));
00256
00257
00258 if ( 0 > lame_init_params( lameGlobalFlags) ) {
00259 throw Exception( __FILE__, __LINE__,
00260 "lame lib initializing params error" );
00261 }
00262
00263 lame_print_config( lameGlobalFlags);
00264
00265 return true;
00266 }
00267
00268
00269
00270
00271
00272 unsigned int
00273 LameLibEncoder :: write ( const void * buf,
00274 unsigned int len ) throw ( Exception )
00275 {
00276 if ( !isOpen() || len == 0 ) {
00277 return 0;
00278 }
00279
00280 unsigned int bitsPerSample = getInBitsPerSample();
00281 unsigned int inChannels = getInChannel();
00282
00283 unsigned int sampleSize = (bitsPerSample / 8) * inChannels;
00284 unsigned char * b = (unsigned char*) buf;
00285 unsigned int processed = len - (len % sampleSize);
00286 unsigned int nSamples = processed / sampleSize;
00287 short int * leftBuffer = new short int[nSamples];
00288 short int * rightBuffer = new short int[nSamples];
00289
00290 if ( bitsPerSample == 8 ) {
00291 Util::conv8( b, processed, leftBuffer, rightBuffer, inChannels);
00292 } else if ( bitsPerSample == 16 ) {
00293 Util::conv16( b,
00294 processed,
00295 leftBuffer,
00296 rightBuffer,
00297 inChannels,
00298 isInBigEndian());
00299 } else {
00300 delete[] leftBuffer;
00301 delete[] rightBuffer;
00302 throw Exception( __FILE__, __LINE__,
00303 "unsupported number of bits per sample for the encoder",
00304 bitsPerSample );
00305 }
00306
00307
00308
00309
00310 unsigned int mp3Size = (unsigned int) (1.25 * nSamples + 7200);
00311 unsigned char * mp3Buf = new unsigned char[mp3Size];
00312 int ret;
00313
00314 ret = lame_encode_buffer( lameGlobalFlags,
00315 leftBuffer,
00316 inChannels == 2 ? rightBuffer : leftBuffer,
00317 nSamples,
00318 mp3Buf,
00319 mp3Size );
00320
00321 delete[] leftBuffer;
00322 delete[] rightBuffer;
00323
00324 if ( ret < 0 ) {
00325 reportEvent( 3, "lame encoding error", ret);
00326 delete[] mp3Buf;
00327 return 0;
00328 }
00329
00330 unsigned int written = sink->write( mp3Buf, ret);
00331 delete[] mp3Buf;
00332
00333 if ( written < (unsigned int) ret ) {
00334 reportEvent( 2,
00335 "couldn't write all from encoder to underlying sink",
00336 ret - written);
00337 }
00338
00339 return processed;
00340 }
00341
00342
00343
00344
00345
00346 void
00347 LameLibEncoder :: flush ( void )
00348 throw ( Exception )
00349 {
00350 if ( !isOpen() ) {
00351 return;
00352 }
00353
00354
00355 unsigned int mp3Size = 7200;
00356 unsigned char * mp3Buf = new unsigned char[mp3Size];
00357 int ret;
00358
00359 ret = lame_encode_flush( lameGlobalFlags, mp3Buf, mp3Size );
00360
00361 unsigned int written = sink->write( mp3Buf, ret);
00362 delete[] mp3Buf;
00363
00364
00365 if ( written < (unsigned int) ret ) {
00366 reportEvent( 2,
00367 "couldn't write all from encoder to underlying sink",
00368 ret - written);
00369 }
00370
00371 sink->flush();
00372 }
00373
00374
00375
00376
00377
00378 void
00379 LameLibEncoder :: close ( void ) throw ( Exception )
00380 {
00381 if ( isOpen() ) {
00382 flush();
00383 lame_close( lameGlobalFlags);
00384 lameGlobalFlags = 0;
00385
00386 sink->close();
00387 }
00388 }
00389
00390
00391 #endif // HAVE_LAME_LIB
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462