Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

TwoLameLibEncoder.cpp

Go to the documentation of this file.
00001 /*------------------------------------------------------------------------------
00002 
00003    Copyright (c) 2005 Tyrell Corporation. All rights reserved.
00004 
00005    Tyrell DarkIce
00006 
00007    File     : TwoLameLibEncoder.cpp
00008    Version  : $Revision: 1.1 $
00009    Author   : $Author: darkeye $
00010    Location : $Source: /cvsroot/darkice/darkice/src/TwoLameLibEncoder.cpp,v $
00011    
00012    Copyright notice:
00013 
00014     This program is free software; you can redistribute it and/or
00015     modify it under the terms of the GNU General Public License  
00016     as published by the Free Software Foundation; either version 2
00017     of the License, or (at your option) any later version.
00018    
00019     This program is distributed in the hope that it will be useful,
00020     but WITHOUT ANY WARRANTY; without even the implied warranty of 
00021     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
00022     GNU General Public License for more details.
00023    
00024     You should have received a copy of the GNU General Public License
00025     along with this program; if not, write to the Free Software
00026     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00027 
00028 ------------------------------------------------------------------------------*/
00029 
00030 /* ============================================================ include files */
00031 
00032 #ifdef HAVE_CONFIG_H
00033 #include "config.h"
00034 #endif
00035 
00036 // compile the whole file only if TwoLame support configured in
00037 #ifdef HAVE_TWOLAME_LIB
00038 
00039 
00040 
00041 #include "Exception.h"
00042 #include "Util.h"
00043 #include "TwoLameLibEncoder.h"
00044 
00045 
00046 /* ===================================================  local data structures */
00047 
00048 
00049 /* ================================================  local constants & macros */
00050 
00051 /*------------------------------------------------------------------------------
00052  *  File identity
00053  *----------------------------------------------------------------------------*/
00054 static const char fileid[] = "$Id: TwoLameLibEncoder.cpp,v 1.1 2006/01/25 22:49:59 darkeye Exp $";
00055 
00056 
00057 /* ===============================================  local function prototypes */
00058 
00059 
00060 /* =============================================================  module code */
00061 
00062 
00063 
00064 /*------------------------------------------------------------------------------
00065  *  Initialize the object
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  *  Open an encoding session
00099  *----------------------------------------------------------------------------*/
00100 bool
00101 TwoLameLibEncoder :: open ( void )
00102                                                             throw ( Exception )
00103 {
00104     if ( isOpen() ) {
00105         close();
00106     }
00107 
00108     // open the underlying sink
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     // ugly twolame returns -1 in a pointer on allocation errors
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     // let TwoLAME init its own params based on our settings
00167     if ( 0 > twolame_init_params( twolame_opts) ) {
00168         throw Exception( __FILE__, __LINE__,
00169                          "TwoLAME lib initializing params error" );
00170     }
00171 
00172     // Information about TwoLame's setup
00173     if (getReportVerbosity() >= 3) {
00174         twolame_print_config( twolame_opts);
00175     }
00176     
00177     return true;
00178 }
00179 
00180 
00181 /*------------------------------------------------------------------------------
00182  *  Write data to the encoder
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     // data chunk size estimate according to TwoLAME documentation
00220     // NOTE: mp2Size is calculated based on the number of input channels
00221     //       which may be bigger than need, as output channels can be less
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     // just let go data that could not be written
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  *  Flush the data from the encoder
00257  *----------------------------------------------------------------------------*/
00258 void
00259 TwoLameLibEncoder :: flush ( void )
00260                                                             throw ( Exception )
00261 {
00262     if ( !isOpen() ) {
00263         return;
00264     }
00265 
00266     // data chunk size estimate according to TwoLAME documentation
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     // just let go data that could not be written
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  *  Close the encoding session
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   $Source: /cvsroot/darkice/darkice/src/TwoLameLibEncoder.cpp,v $
00307 
00308   $Log: TwoLameLibEncoder.cpp,v $
00309   Revision 1.1  2006/01/25 22:49:59  darkeye
00310   added mpeg2 support thanks to Nicholas J Humfrey
00311 
00312 
00313   Revision 1.1  2005/05/02 23:05:02  nhumfrey
00314   initial version - based on LameLibEncoder 1.19
00315   
00316 ------------------------------------------------------------------------------*/
00317 

Generated on Fri May 19 15:36:48 2006 for DarkIce by  doxygen 1.4.4