1 /*------------------------------------------------------------------------------
2 
3    Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
4 
5    Tyrell DarkIce
6 
7    File     : FaacEncoder.h
8    Version  : $Revision$
9    Author   : $Author$
10    Location : $HeadURL$
11 
12    Copyright notice:
13 
14     This program is free software; you can redistribute it and/or
15     modify it under the terms of the GNU General Public License
16     as published by the Free Software Foundation; either version 3
17     of the License, or (at your option) any later version.
18 
19     This program is distributed in the hope that it will be useful,
20     but WITHOUT ANY WARRANTY; without even the implied warranty of
21     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22     GNU General Public License for more details.
23 
24     You should have received a copy of the GNU General Public License
25     along with this program; if not, write to the Free Software
26     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27 
28 ------------------------------------------------------------------------------*/
29 #ifndef AAC_ENCODER_H
30 #define AAC_ENCODER_H
31 
32 #ifndef __cplusplus
33 #error This is a C++ include file
34 #endif
35 
36 
37 /* ============================================================ include files */
38 
39 #ifdef HAVE_CONFIG_H
40 #include "config.h"
41 #endif
42 
43 #ifdef HAVE_FAAC_LIB
44 #include <faac.h>
45 #else
46 #error configure with faac
47 #endif
48 
49 
50 #include "Ref.h"
51 #include "Exception.h"
52 #include "Reporter.h"
53 #include "AudioEncoder.h"
54 #include "Sink.h"
55 #ifdef HAVE_SRC_LIB
56 #include <samplerate.h>
57 #else
58 #include "aflibConverter.h"
59 #endif
60 
61 
62 /* ================================================================ constants */
63 
64 
65 /* =================================================================== macros */
66 
67 
68 /* =============================================================== data types */
69 
70 /**
71  *  A class representing faac AAC encoder.
72  *
73  *  @author  $Author$
74  *  @version $Revision$
75  */
76 class FaacEncoder : public AudioEncoder, public virtual Reporter
77 {
78     private:
79 
80         /**
81          *  A flag to indicate if the encoding session is open.
82          */
83         bool                        faacOpen;
84 
85         /**
86          *  The handle to the AAC encoder instance.
87          */
88         faacEncHandle               encoderHandle;
89 
90         /**
91          *  The maximum number of input samples to supply to the encoder.
92          */
93         unsigned long               inputSamples;
94 
95         /**
96          *  The maximum number of output bytes the encoder returns in one call.
97          */
98         unsigned long               maxOutputBytes;
99 
100         /**
101          *  Lowpass filter. Sound frequency in Hz, from where up the
102          *  input is cut.
103          */
104         int                             lowpass;
105 
106         /**
107          *  Resample ratio
108          */
109         double                      resampleRatio;
110 
111         /**
112          *  sample rate converter object for possible resampling
113          */
114 #ifdef HAVE_SRC_LIB
115         SRC_STATE                   *converter;
116         SRC_DATA                    converterData;
117         float                       *resampledOffset;
118 #else
119         aflibConverter              *converter;
120         short                       *resampledOffset;
121 #endif
122         unsigned int                resampledOffsetSize;
123 
124         /**
125          *  Initialize the object.
126          *
127          *  @param lowpass frequency threshold for the lowpass filter.
128          *                 Input above this frequency is cut.
129          *                 If 0, faac's default values are used,
130          *                 which depends on the out sample rate.
131          *  @exception Exception
132          */
133         inline void
init(int lowpass)134         init ( int              lowpass)                throw (Exception)
135         {
136             this->faacOpen        = false;
137             this->lowpass         = lowpass;
138 
139             if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 8 ) {
140                 throw Exception( __FILE__, __LINE__,
141                                  "specified bits per sample not supported",
142                                  getInBitsPerSample() );
143             }
144 
145             if ( getInChannel() != 1 && getInChannel() != 2 ) {
146                 throw Exception( __FILE__, __LINE__,
147                          "unsupported number of input channels for the encoder",
148                                  getInChannel() );
149             }
150             if ( getOutChannel() != 1 && getOutChannel() != 2 ) {
151                 throw Exception( __FILE__, __LINE__,
152                         "unsupported number of output channels for the encoder",
153                                  getOutChannel() );
154             }
155             if ( getInChannel() != getOutChannel() ) {
156                 throw Exception( __FILE__, __LINE__,
157                              "input channels and output channels do not match");
158             }
159             if ( getOutSampleRate() == getInSampleRate() ) {
160                 resampleRatio = 1;
161                 converter     = 0;
162             } else if (getInBitsPerSample() == 16) {
163                 resampleRatio = ( (double) getOutSampleRate() /
164                                   (double) getInSampleRate() );
165 
166                 // Determine if we can use linear interpolation.
167                 // The inverse of the ratio must be a power of two for linear mode to
168                 // be of sufficient quality.
169 
170                 bool    useLinear = true;
171                 double  inverse   = 1 / resampleRatio;
172                 int     integer   = (int) inverse;
173 
174                 // Check that the inverse of the ratio is an integer
175                 if( integer == inverse ) {
176                     while( useLinear && integer ) { // Loop through the bits
177                         // If the lowest order bit is not the only one set
178                         if( integer & 1 && integer != 1 ) {
179                             // Not a power of two; cannot use linear
180                             useLinear = false;
181                         } else {
182                             // Shift all the bits over and try again
183                             integer >>= 1;
184                         }
185                     }
186                 } else {
187                    useLinear = false;
188                 }
189 
190                 // If we get here and useLinear is still true, then we have
191                 // a power of two.
192 
193                 // open the aflibConverter in
194                 // - high quality
195                 // - linear or quadratic (non-linear) based on algorithm
196                 // - not filter interpolation
197 #ifdef HAVE_SRC_LIB
198                 int srcError = 0;
199                 converter = src_new(useLinear == true ? SRC_LINEAR : SRC_SINC_FASTEST,
200                                     getInChannel(), &srcError);
201                 if(srcError)
202                     throw Exception (__FILE__, __LINE__, "libsamplerate error: ", src_strerror (srcError));
203 #else
204                 converter = new aflibConverter( true, useLinear, false);
205 #endif
206             } else {
207                 throw Exception( __FILE__, __LINE__,
208                                  "specified bits per sample with samplerate conversion not supported",
209                                  getInBitsPerSample() );
210             }
211         }
212 
213         /**
214          *  De-initialize the object.
215          *
216          *  @exception Exception
217          */
218         inline void
strip(void)219         strip ( void )                                  throw ( Exception )
220         {
221             if ( converter ) {
222 #ifdef HAVE_SRC_LIB
223                 delete [] converterData.data_in;
224                 src_delete (converter);
225 #else
226                 delete converter;
227 #endif
228                 delete [] resampledOffset;
229             }
230         }
231 
232 
233     protected:
234 
235         /**
236          *  Default constructor. Always throws an Exception.
237          *
238          *  @exception Exception
239          */
240         inline
FaacEncoder(void)241         FaacEncoder ( void )                         throw ( Exception )
242         {
243             throw Exception( __FILE__, __LINE__);
244         }
245 
246 
247     public:
248 
249         /**
250          *  Constructor.
251          *
252          *  @param sink the sink to send mp3 output to
253          *  @param inSampleRate sample rate of the input.
254          *  @param inBitsPerSample number of bits per sample of the input.
255          *  @param inChannel number of channels  of the input.
256          *  @param inBigEndian shows if the input is big or little endian
257          *  @param outBitrateMode the bit rate mode of the output.
258          *  @param outBitrate bit rate of the output (kbits/sec).
259          *  @param outQuality the quality of the stream.
260          *  @param outSampleRate sample rate of the output.
261          *                       If 0, inSampleRate is used.
262          *  @param outChannel number of channels of the output.
263          *                    If 0, inChannel is used.
264          *  @param lowpass frequency threshold for the lowpass filter.
265          *                 Input above this frequency is cut.
266          *                 If 0, faac's default values are used,
267          *                 which depends on the out sample rate.
268          *  @exception Exception
269          */
270         inline
271         FaacEncoder (   Sink          * sink,
272                         unsigned int    inSampleRate,
273                         unsigned int    inBitsPerSample,
274                         unsigned int    inChannel,
275                         bool            inBigEndian,
276                         BitrateMode     outBitrateMode,
277                         unsigned int    outBitrate,
278                         double          outQuality,
279                         unsigned int    outSampleRate = 0,
280                         unsigned int    outChannel    = 0,
281                         int             lowpass       = 0)
throw(Exception)282                                                         throw ( Exception )
283 
284                     : AudioEncoder ( sink,
285                                      inSampleRate,
286                                      inBitsPerSample,
287                                      inChannel,
288                                      inBigEndian,
289                                      outBitrateMode,
290                                      outBitrate,
291                                      outQuality,
292                                      outSampleRate,
293                                      outChannel )
294         {
295             init( lowpass);
296         }
297 
298         /**
299          *  Constructor.
300          *
301          *  @param sink the sink to send mp3 output to
302          *  @param as get input sample rate, bits per sample and channels
303          *            from this AudioSource.
304          *  @param outBitrateMode the bit rate mode of the output.
305          *  @param outBitrate bit rate of the output (kbits/sec).
306          *  @param outQuality the quality of the stream.
307          *  @param outSampleRate sample rate of the output.
308          *                       If 0, input sample rate is used.
309          *  @param outChannel number of channels of the output.
310          *                    If 0, input channel is used.
311          *  @param lowpass frequency threshold for the lowpass filter.
312          *                 Input above this frequency is cut.
313          *                 If 0, faac's default values are used,
314          *                 which depends on the out sample rate.
315          *  @exception Exception
316          */
317         inline
318         FaacEncoder (   Sink                  * sink,
319                         const AudioSource     * as,
320                         BitrateMode             outBitrateMode,
321                         unsigned int            outBitrate,
322                         double                  outQuality,
323                         unsigned int            outSampleRate = 0,
324                         unsigned int            outChannel    = 0,
325                         int                     lowpass       = 0)
throw(Exception)326                                                             throw ( Exception )
327 
328                     : AudioEncoder ( sink,
329                                      as,
330                                      outBitrateMode,
331                                      outBitrate,
332                                      outQuality,
333                                      outSampleRate,
334                                      outChannel )
335         {
336             init( lowpass);
337         }
338 
339         /**
340          *  Copy constructor.
341          *
342          *  @param encoder the FaacEncoder to copy.
343          */
344         inline
345         FaacEncoder (  const FaacEncoder &    encoder )
throw(Exception)346                                                             throw ( Exception )
347                     : AudioEncoder( encoder )
348         {
349             init( encoder.lowpass);
350         }
351 
352 
353         /**
354          *  Destructor.
355          *
356          *  @exception Exception
357          */
358         inline virtual
~FaacEncoder(void)359         ~FaacEncoder ( void )                            throw ( Exception )
360         {
361             if ( isOpen() ) {
362                 close();
363             }
364             strip();
365         }
366 
367         /**
368          *  Assignment operator.
369          *
370          *  @param encoder the FaacEncoder to assign this to.
371          *  @return a reference to this FaacEncoder.
372          *  @exception Exception
373          */
374         inline virtual FaacEncoder &
throw(Exception)375         operator= ( const FaacEncoder &      encoder )   throw ( Exception )
376         {
377             if ( this != &encoder ) {
378                 strip();
379                 AudioEncoder::operator=( encoder);
380                 init( encoder.lowpass);
381             }
382 
383             return *this;
384         }
385 
386         /**
387          *  Get the version string of the underlying faac library.
388          *
389          *  @return the version string of the underlying faac library.
390          */
391         inline const char *
getFaacVersion(void)392         getFaacVersion( void )
393         {
394             char      * id;
395             char      * copyright;
396 
397             faacEncGetVersion(&id, &copyright);
398             return id;
399         }
400 
401         /**
402          *  Check whether encoding is in progress.
403          *
404          *  @return true if encoding is in progress, false otherwise.
405          */
406         inline virtual bool
isRunning(void)407         isRunning ( void ) const           throw ()
408         {
409             return isOpen();
410         }
411 
412         /**
413          *  Start encoding. This function returns as soon as possible,
414          *  with encoding started in the background.
415          *
416          *  @return true if encoding has started, false otherwise.
417          *  @exception Exception
418          */
419         inline virtual bool
start(void)420         start ( void )                      throw ( Exception )
421         {
422             return open();
423         }
424 
425         /**
426          *  Stop encoding. Stops the encoding running in the background.
427          *
428          *  @exception Exception
429          */
430         inline virtual void
stop(void)431         stop ( void )                       throw ( Exception )
432         {
433             return close();
434         }
435 
436         /**
437          *  Open an encoding session.
438          *
439          *  @return true if opening was successfull, false otherwise.
440          *  @exception Exception
441          */
442         virtual bool
443         open ( void )                               throw ( Exception );
444 
445         /**
446          *  Check if the encoding session is open.
447          *
448          *  @return true if the encoding session is open, false otherwise.
449          */
450         inline virtual bool
isOpen(void)451         isOpen ( void ) const                       throw ()
452         {
453             return faacOpen;
454         }
455 
456         /**
457          *  Check if the encoder is ready to accept data.
458          *
459          *  @param sec the maximum seconds to block.
460          *  @param usec micro seconds to block after the full seconds.
461          *  @return true if the encoder is ready to accept data,
462          *          false otherwise.
463          *  @exception Exception
464          */
465         inline virtual bool
canWrite(unsigned int sec,unsigned int usec)466         canWrite (     unsigned int    sec,
467                        unsigned int    usec )       throw ( Exception )
468         {
469             if ( !isOpen() ) {
470                 return false;
471             }
472 
473             return true;
474         }
475 
476         /**
477          *  Write data to the encoder.
478          *  Buf is expected to be a sequence of big-endian 16 bit values,
479          *  with left and right channels interleaved. Len is the number of
480          *  bytes, must be a multiple of 4.
481          *
482          *  @param buf the data to write.
483          *  @param len number of bytes to write from buf.
484          *  @return the number of bytes written (may be less than len).
485          *  @exception Exception
486          */
487         virtual unsigned int
488         write (        const void    * buf,
489                        unsigned int    len )        throw ( Exception );
490 
491         /**
492          *  Flush all data that was written to the encoder to the underlying
493          *  connection.
494          *
495          *  @exception Exception
496          */
497         virtual void
498         flush ( void )                              throw ( Exception );
499 
500         /**
501          *  Close the encoding session.
502          *
503          *  @exception Exception
504          */
505         virtual void
506         close ( void )                              throw ( Exception );
507 };
508 
509 
510 /* ================================================= external data structures */
511 
512 
513 /* ====================================================== function prototypes */
514 
515 
516 #endif  /* AAC_ENCODER_H */
517 
518