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_TWOLAME_LIB
00038
00039
00040
00041 #include "Exception.h"
00042 #include "Util.h"
00043 #include "TwoLameLibEncoder.h"
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 static const char fileid[] = "$Id: TwoLameLibEncoder.cpp,v 1.1 2006/01/25 22:49:59 darkeye Exp $";
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 void
00068 TwoLameLibEncoder :: init ( Sink * sink ) throw ( Exception )
00069 {
00070 this->twolame_opts = NULL;
00071 this->sink = sink;
00072
00073 if ( getInBitsPerSample() != 16 ) {
00074 throw Exception( __FILE__, __LINE__,
00075 "specified bits per sample not supported",
00076 getInBitsPerSample() );
00077 }
00078
00079 if ( getInChannel() != 1 && getInChannel() != 2 ) {
00080 throw Exception( __FILE__, __LINE__,
00081 "unsupported number of input channels for the encoder",
00082 getInChannel() );
00083 }
00084 if ( getOutChannel() != 1 && getOutChannel() != 2 ) {
00085 throw Exception( __FILE__, __LINE__,
00086 "unsupported number of output channels for the encoder",
00087 getOutChannel() );
00088 }
00089 if ( getInChannel() < getOutChannel() ) {
00090 throw Exception( __FILE__, __LINE__,
00091 "output channels greater then input channels",
00092 getOutChannel() );
00093 }
00094 }
00095
00096
00097
00098
00099
00100 bool
00101 TwoLameLibEncoder :: open ( void )
00102 throw ( Exception )
00103 {
00104 if ( isOpen() ) {
00105 close();
00106 }
00107
00108
00109 if ( !sink->open() ) {
00110 throw Exception( __FILE__, __LINE__,
00111 "TwoLAME lib opening underlying sink error");
00112 }
00113
00114 twolame_opts = ::twolame_init();
00115
00116
00117 if ( !twolame_opts ) {
00118 throw Exception( __FILE__, __LINE__,
00119 "TwoLAME lib init error",
00120 (int) twolame_opts);
00121 }
00122
00123 if ( 0 > twolame_set_num_channels( twolame_opts, getInChannel()) ) {
00124 throw Exception( __FILE__, __LINE__,
00125 "TwoLAME lib setting channels error",
00126 getInChannel() );
00127 }
00128
00129 if ( 0 > twolame_set_mode( twolame_opts,
00130 getOutChannel() == 1 ? TWOLAME_MONO : TWOLAME_JOINT_STEREO) ) {
00131 throw Exception( __FILE__, __LINE__,
00132 "TwoLAME lib setting mode error",
00133 TWOLAME_JOINT_STEREO );
00134 }
00135
00136 if ( 0 > twolame_set_in_samplerate( twolame_opts, getInSampleRate()) ) {
00137 throw Exception( __FILE__, __LINE__,
00138 "TwoLAME lib setting input sample rate error",
00139 getInSampleRate() );
00140 }
00141
00142 if ( 0 > twolame_set_out_samplerate( twolame_opts, getOutSampleRate()) ) {
00143 throw Exception( __FILE__, __LINE__,
00144 "TwoLAME lib setting output sample rate error",
00145 getOutSampleRate() );
00146 }
00147
00148 switch ( getOutBitrateMode() ) {
00149
00150 case cbr: {
00151
00152 if ( 0 > twolame_set_brate( twolame_opts, getOutBitrate()) ) {
00153 throw Exception( __FILE__, __LINE__,
00154 "TwoLAME lib setting output bit rate error",
00155 getOutBitrate() );
00156 }
00157 } break;
00158
00159 default: {
00160 throw Exception( __FILE__, __LINE__,
00161 "Unsupported bitrate mode." );
00162 }
00163 }
00164
00165
00166
00167 if ( 0 > twolame_init_params( twolame_opts) ) {
00168 throw Exception( __FILE__, __LINE__,
00169 "TwoLAME lib initializing params error" );
00170 }
00171
00172
00173 if (getReportVerbosity() >= 3) {
00174 twolame_print_config( twolame_opts);
00175 }
00176
00177 return true;
00178 }
00179
00180
00181
00182
00183
00184 unsigned int
00185 TwoLameLibEncoder :: write ( const void * buf,
00186 unsigned int len ) throw ( Exception )
00187 {
00188 if ( !isOpen() || len == 0 ) {
00189 return 0;
00190 }
00191
00192 unsigned int bitsPerSample = getInBitsPerSample();
00193 unsigned int inChannels = getInChannel();
00194
00195 unsigned int sampleSize = (bitsPerSample / 8) * inChannels;
00196 unsigned char * b = (unsigned char*) buf;
00197 unsigned int processed = len - (len % sampleSize);
00198 unsigned int nSamples = processed / sampleSize;
00199 short int * leftBuffer = new short int[nSamples];
00200 short int * rightBuffer = new short int[nSamples];
00201
00202 if ( bitsPerSample == 8 ) {
00203 Util::conv8( b, processed, leftBuffer, rightBuffer, inChannels);
00204 } else if ( bitsPerSample == 16 ) {
00205 Util::conv16( b,
00206 processed,
00207 leftBuffer,
00208 rightBuffer,
00209 inChannels,
00210 isInBigEndian());
00211 } else {
00212 delete[] leftBuffer;
00213 delete[] rightBuffer;
00214 throw Exception( __FILE__, __LINE__,
00215 "unsupported number of bits per sample for the encoder",
00216 bitsPerSample );
00217 }
00218
00219
00220
00221
00222 unsigned int mp2Size = (unsigned int) (1.25 * nSamples + 7200);
00223 unsigned char * mp2Buf = new unsigned char[mp2Size];
00224 int ret;
00225
00226 ret = twolame_encode_buffer( twolame_opts,
00227 leftBuffer,
00228 inChannels == 2 ? rightBuffer : leftBuffer,
00229 nSamples,
00230 mp2Buf,
00231 mp2Size );
00232
00233 delete[] leftBuffer;
00234 delete[] rightBuffer;
00235
00236 if ( ret < 0 ) {
00237 reportEvent( 3, "TwoLAME encoding error", ret);
00238 delete[] mp2Buf;
00239 return 0;
00240 }
00241
00242 unsigned int written = sink->write( mp2Buf, ret);
00243 delete[] mp2Buf;
00244
00245 if ( written < (unsigned int) ret ) {
00246 reportEvent( 2,
00247 "couldn't write all from encoder to underlying sink",
00248 ret - written);
00249 }
00250
00251 return processed;
00252 }
00253
00254
00255
00256
00257
00258 void
00259 TwoLameLibEncoder :: flush ( void )
00260 throw ( Exception )
00261 {
00262 if ( !isOpen() ) {
00263 return;
00264 }
00265
00266
00267 unsigned int mp2Size = 7200;
00268 unsigned char * mp2Buf = new unsigned char[mp2Size];
00269 int ret;
00270
00271 ret = twolame_encode_flush( twolame_opts, mp2Buf, mp2Size );
00272
00273 unsigned int written = sink->write( mp2Buf, ret);
00274 delete[] mp2Buf;
00275
00276
00277 if ( written < (unsigned int) ret ) {
00278 reportEvent( 2,
00279 "couldn't write all from encoder to underlying sink",
00280 ret - written);
00281 }
00282
00283 sink->flush();
00284 }
00285
00286
00287
00288
00289
00290 void
00291 TwoLameLibEncoder :: close ( void ) throw ( Exception )
00292 {
00293 if ( isOpen() ) {
00294 flush();
00295 twolame_close( &twolame_opts );
00296 sink->close();
00297 }
00298 }
00299
00300
00301 #endif // HAVE_TWOLAME_LIB
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317