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, ©right); 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