added AAC support through the faac codec, http://www.audiocoding.com/

This commit is contained in:
darkeye 2005-04-16 21:57:34 +00:00
parent 2ebf68e42a
commit 9a23ebe086
10 changed files with 772 additions and 8 deletions

View File

@ -1,3 +1,7 @@
DarkIce next version
o added AAC support through the faac codec, http://www.audiocoding.com
14-04-2005 DarkIce 0.15 released
o ported to OpenBSD and NetBSD, though real-time scheduling not supported,

View File

@ -1,5 +1,5 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(darkice, 0.15)
AC_INIT(darkice, 0.16beta)
AC_CONFIG_SRCDIR(src/DarkIce.cpp)
AM_CONFIG_HEADER(src/config.h)
@ -115,6 +115,40 @@ else
fi
dnl-----------------------------------------------------------------------------
dnl link the faac library if requested
dnl-----------------------------------------------------------------------------
AC_SUBST( FAAC_INCFLAGS)
AC_SUBST( FAAC_LDFLAGS)
AC_ARG_WITH( faac,
[ --with-faac use faac for encoding AAC streams [yes] ],
USE_FAAC=${withval}, USE_FAAC="yes" )
AC_ARG_WITH( faac-prefix,
[ --with-faac-prefix=DIR alternate location for faac [/usr]
look for libraries in FAAC-PREFIX/lib,
for headers in FAAC-PREFIX/include],
CONFIG_FAAC_PREFIX="${withval}", CONFIG_FAAC_PREFIX="/usr")
if test "x${USE_FAAC}" = "xyes" ; then
AC_MSG_CHECKING( [for faac library at ${CONFIG_FAAC_PREFIX}] )
LA_SEARCH_LIB( FAAC_LIB_LOC, FAAC_INC_LOC, libfaac.a, faac.h,
${CONFIG_FAAC_PREFIX})
if test "x${FAAC_LIB_LOC}" != "x" ; then
AC_DEFINE( HAVE_FAAC_LIB, 1, [build with faac library] )
if test "x${FAAC_INC_LOC}" != "x${SYSTEM_INCLUDE}" ; then
FAAC_INCFLAGS="-I${FAAC_INC_LOC}"
fi
FAAC_LDFLAGS="-L${FAAC_LIB_LOC} -lfaac"
AC_MSG_RESULT( [found at ${CONFIG_FAAC_PREFIX}] )
else
AC_MSG_WARN( [not found, building without faac])
fi
else
AC_MSG_RESULT( [building without faac] )
fi
dnl-----------------------------------------------------------------------------
dnl make sure at least one of lame and vorbis present
dnl-----------------------------------------------------------------------------

View File

@ -88,6 +88,10 @@
#include "VorbisLibEncoder.h"
#endif
#ifdef HAVE_FAAC_LIB
#include "FaacEncoder.h"
#endif
/* =================================================== local data structures */
@ -395,6 +399,8 @@ DarkIce :: configIceCast2 ( const Config & config,
format = IceCast2::oggVorbis;
} else if ( Util::strEq( str, "mp3") ) {
format = IceCast2::mp3;
} else if ( Util::strEq( str, "aac") ) {
format = IceCast2::aac;
} else {
throw Exception( __FILE__, __LINE__,
"unsupported stream format: ", str);
@ -534,6 +540,24 @@ DarkIce :: configIceCast2 ( const Config & config,
#endif // HAVE_VORBIS_LIB
break;
case IceCast2::aac:
#ifndef HAVE_FAAC_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with AAC support, "
"thus can't aac stream: ",
stream);
#else
audioOuts[u].encoder = new FaacEncoder(
audioOuts[u].server.get(),
dsp.get(),
bitrateMode,
bitrate,
quality,
sampleRate,
dsp->getChannel());
#endif // HAVE_FAAC_LIB
break;
default:
throw Exception( __FILE__, __LINE__,
"Illegal stream format: ", format);
@ -753,7 +777,9 @@ DarkIce :: configFileCast ( const Config & config )
int highpass = 0;
format = cs->getForSure( "format", " missing in section ", stream);
if ( !Util::strEq( format, "vorbis") && !Util::strEq( format, "mp3") ) {
if ( !Util::strEq( format, "vorbis")
&& !Util::strEq( format, "mp3")
&& !Util::strEq( format, "aac") ) {
throw Exception( __FILE__, __LINE__,
"unsupported stream format: ", format);
}
@ -804,6 +830,12 @@ DarkIce :: configFileCast ( const Config & config )
"invalid bitrate mode: ", str);
}
if (Util::strEq(format, "aac") && bitrateMode != AudioEncoder::abr) {
throw Exception(__FILE__, __LINE__,
"currently the AAC format only supports "
"average bitrate mode");
}
str = cs->get( "lowpass");
lowpass = str ? Util::strToL( str) : 0;
str = cs->get( "highpass");
@ -858,6 +890,22 @@ DarkIce :: configFileCast ( const Config & config )
dsp->getSampleRate(),
dsp->getChannel() );
#endif // HAVE_VORBIS_LIB
} else if ( Util::strEq( format, "aac") ) {
#ifndef HAVE_FAAC_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with AAC support, "
"thus can't aac stream: ",
stream);
#else
audioOuts[u].encoder = new FaacEncoder(
audioOuts[u].server.get(),
dsp.get(),
bitrateMode,
bitrate,
quality,
sampleRate,
dsp->getChannel());
#endif // HAVE_FAAC_LIB
} else {
throw Exception( __FILE__, __LINE__,
"Illegal stream format: ", format);
@ -1011,6 +1059,9 @@ DarkIce :: run ( void ) throw ( Exception )
$Source$
$Log$
Revision 1.44 2005/04/16 21:57:34 darkeye
added AAC support through the faac codec, http://www.audiocoding.com/
Revision 1.43 2005/04/11 19:27:43 darkeye
added option to turn off automatic reconnect feature

View File

@ -0,0 +1,204 @@
/*------------------------------------------------------------------------------
Copyright (c) 2005 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : FaacEncoder.cpp
Version : $Revision$
Author : $Author$
Location : $Source$
Copyright notice:
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
------------------------------------------------------------------------------*/
/* ============================================================ include files */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
// compile the whole file only if lame support configured in
#ifdef HAVE_FAAC_LIB
#include "Exception.h"
#include "Util.h"
#include "FaacEncoder.h"
/* =================================================== local data structures */
/* ================================================ local constants & macros */
/*------------------------------------------------------------------------------
* File identity
*----------------------------------------------------------------------------*/
static const char fileid[] = "$Id$";
/* =============================================== local function prototypes */
/* ============================================================= module code */
/*------------------------------------------------------------------------------
* Open an encoding session
*----------------------------------------------------------------------------*/
bool
FaacEncoder :: open ( void )
throw ( Exception )
{
if ( isOpen() ) {
close();
}
// open the underlying sink
if ( !sink->open() ) {
throw Exception( __FILE__, __LINE__,
"faac lib opening underlying sink error");
}
char * faacVersion;
char * faacCopyright;
faacEncGetVersion(&faacVersion, &faacCopyright);
reportEvent(1, "Using faac codec version", faacVersion);
encoderHandle = faacEncOpen(getInSampleRate(),
getInChannel(),
&inputSamples,
&maxOutputBytes);
faacEncConfiguration * faacConfig;
faacConfig = faacEncGetCurrentConfiguration(encoderHandle);
faacConfig->aacObjectType = MAIN;
faacConfig->mpegVersion = MPEG2;
faacConfig->useTns = 1;
faacConfig->shortctl = SHORTCTL_NORMAL;
faacConfig->useLfe = 0;
faacConfig->allowMidside = 1;
faacConfig->bitRate = getOutBitrate() * 1000 / getOutChannel();
faacConfig->bandWidth = lowpass;
faacConfig->quantqual = (unsigned long) (getOutQuality() * 1000.0);
faacConfig->outputFormat = 1;
faacConfig->inputFormat = FAAC_INPUT_16BIT;
if (!faacEncSetConfiguration(encoderHandle, faacConfig)) {
throw Exception(__FILE__, __LINE__,
"error configuring faac library");
}
faacOpen = true;
return true;
}
/*------------------------------------------------------------------------------
* Write data to the encoder
*----------------------------------------------------------------------------*/
unsigned int
FaacEncoder :: write ( const void * buf,
unsigned int len ) throw ( Exception )
{
if ( !isOpen() || len == 0 ) {
return 0;
}
unsigned int channels = getInChannel();
unsigned int bitsPerSample = getInBitsPerSample();
unsigned int sampleSize = (bitsPerSample / 8) * channels;
unsigned char * b = (unsigned char*) buf;
unsigned int processed = len - (len % sampleSize);
unsigned int nSamples = processed / sampleSize;
unsigned char * faacBuf = new unsigned char[maxOutputBytes];
int samples = (int) nSamples * channels;
int processedSamples = 0;
while (processedSamples < samples) {
int outputBytes;
int inSamples = samples - processedSamples < (int) inputSamples
? samples - processedSamples
: inputSamples;
outputBytes = faacEncEncode(encoderHandle,
(int32_t*) (b + processedSamples/sampleSize),
inSamples,
faacBuf,
maxOutputBytes);
sink->write(faacBuf, outputBytes);
processedSamples += inSamples;
}
delete[] faacBuf;
return processedSamples;
}
/*------------------------------------------------------------------------------
* Flush the data from the encoder
*----------------------------------------------------------------------------*/
void
FaacEncoder :: flush ( void )
throw ( Exception )
{
if ( !isOpen() ) {
return;
}
sink->flush();
}
/*------------------------------------------------------------------------------
* Close the encoding session
*----------------------------------------------------------------------------*/
void
FaacEncoder :: close ( void ) throw ( Exception )
{
if ( isOpen() ) {
flush();
faacEncClose(encoderHandle);
faacOpen = false;
sink->close();
}
}
#endif // HAVE_FAAC_LIB
/*------------------------------------------------------------------------------
$Source$
$Log$
Revision 1.1 2005/04/16 21:57:34 darkeye
added AAC support through the faac codec, http://www.audiocoding.com/
------------------------------------------------------------------------------*/

View File

@ -0,0 +1,451 @@
/*------------------------------------------------------------------------------
Copyright (c) 2005 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : FaacEncoder.h
Version : $Revision$
Author : $Author$
Location : $Source$
Copyright notice:
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
------------------------------------------------------------------------------*/
#ifndef AAC_ENCODER_H
#define AAC_ENCODER_H
#ifndef __cplusplus
#error This is a C++ include file
#endif
/* ============================================================ include files */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_FAAC_LIB
#include <faac.h>
#else
#error configure with faac
#endif
#include "Ref.h"
#include "Exception.h"
#include "Reporter.h"
#include "AudioEncoder.h"
#include "Sink.h"
/* ================================================================ constants */
/* =================================================================== macros */
/* =============================================================== data types */
/**
* A class representing faac AAC encoder.
*
* @author $Author$
* @version $Revision$
*/
class FaacEncoder : public AudioEncoder, public virtual Reporter
{
private:
/**
* A flag to indicate if the encoding session is open.
*/
bool faacOpen;;
/**
* The handle to the AAC encoder instance.
*/
faacEncHandle encoderHandle;
/**
* The maximum number of input samples to supply to the encoder.
*/
unsigned long inputSamples;
/**
* The maximum number of output bytes the encoder returns in one call.
*/
unsigned long maxOutputBytes;
/**
* Lowpass filter. Sound frequency in Hz, from where up the
* input is cut.
*/
int lowpass;
/**
* The Sink to dump mp3 data to
*/
Ref<Sink> sink;
/**
* Initialize the object.
*
* @param sink the sink to send mp3 output to
* @param lowpass frequency threshold for the lowpass filter.
* Input above this frequency is cut.
* If 0, lame's default values are used,
* which depends on the out sample rate.
* @exception Exception
*/
inline void
init ( Sink * sink,
int lowpass) throw (Exception)
{
this->sink = sink;
this->lowpass = lowpass;
if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 8 ) {
throw Exception( __FILE__, __LINE__,
"specified bits per sample not supported",
getInBitsPerSample() );
}
if ( getInChannel() != 1 && getInChannel() != 2 ) {
throw Exception( __FILE__, __LINE__,
"unsupported number of input channels for the encoder",
getInChannel() );
}
if ( getOutChannel() != 1 && getOutChannel() != 2 ) {
throw Exception( __FILE__, __LINE__,
"unsupported number of output channels for the encoder",
getOutChannel() );
}
if ( getInChannel() != getOutChannel() ) {
throw Exception( __FILE__, __LINE__,
"input channels and output channels do not match");
}
}
/**
* De-initialize the object.
*
* @exception Exception
*/
inline void
strip ( void ) throw ( Exception )
{
}
protected:
/**
* Default constructor. Always throws an Exception.
*
* @exception Exception
*/
inline
FaacEncoder ( void ) throw ( Exception )
{
throw Exception( __FILE__, __LINE__);
}
public:
/**
* Constructor.
*
* @param sink the sink to send mp3 output to
* @param inSampleRate sample rate of the input.
* @param inBitsPerSample number of bits per sample of the input.
* @param inChannel number of channels of the input.
* @param inBigEndian shows if the input is big or little endian
* @param outBitrateMode the bit rate mode of the output.
* @param outBitrate bit rate of the output (kbits/sec).
* @param outQuality the quality of the stream.
* @param outSampleRate sample rate of the output.
* If 0, inSampleRate is used.
* @param outChannel number of channels of the output.
* If 0, inChannel is used.
* @param lowpass frequency threshold for the lowpass filter.
* Input above this frequency is cut.
* If 0, lame's default values are used,
* which depends on the out sample rate.
* @exception Exception
*/
inline
FaacEncoder ( Sink * sink,
unsigned int inSampleRate,
unsigned int inBitsPerSample,
unsigned int inChannel,
bool inBigEndian,
BitrateMode outBitrateMode,
unsigned int outBitrate,
double outQuality,
unsigned int outSampleRate = 0,
unsigned int outChannel = 0,
int lowpass = 0)
throw ( Exception )
: AudioEncoder ( inSampleRate,
inBitsPerSample,
inChannel,
inBigEndian,
outBitrateMode,
outBitrate,
outQuality,
outSampleRate,
outChannel )
{
init( sink, lowpass);
}
/**
* Constructor.
*
* @param sink the sink to send mp3 output to
* @param as get input sample rate, bits per sample and channels
* from this AudioSource.
* @param outBitrateMode the bit rate mode of the output.
* @param outBitrate bit rate of the output (kbits/sec).
* @param outQuality the quality of the stream.
* @param outSampleRate sample rate of the output.
* If 0, input sample rate is used.
* @param outChannel number of channels of the output.
* If 0, input channel is used.
* @param lowpass frequency threshold for the lowpass filter.
* Input above this frequency is cut.
* If 0, lame's default values are used,
* which depends on the out sample rate.
* @exception Exception
*/
inline
FaacEncoder ( Sink * sink,
const AudioSource * as,
BitrateMode outBitrateMode,
unsigned int outBitrate,
double outQuality,
unsigned int outSampleRate = 0,
unsigned int outChannel = 0,
int lowpass = 0)
throw ( Exception )
: AudioEncoder ( as,
outBitrateMode,
outBitrate,
outQuality,
outSampleRate,
outChannel )
{
init( sink, lowpass);
}
/**
* Copy constructor.
*
* @param encoder the FaacEncoder to copy.
*/
inline
FaacEncoder ( const FaacEncoder & encoder )
throw ( Exception )
: AudioEncoder( encoder )
{
init( encoder.sink.get(), encoder.lowpass);
}
/**
* Destructor.
*
* @exception Exception
*/
inline virtual
~FaacEncoder ( void ) throw ( Exception )
{
if ( isOpen() ) {
close();
}
strip();
}
/**
* Assignment operator.
*
* @param encoder the FaacEncoder to assign this to.
* @return a reference to this FaacEncoder.
* @exception Exception
*/
inline virtual FaacEncoder &
operator= ( const FaacEncoder & encoder ) throw ( Exception )
{
if ( this != &encoder ) {
strip();
AudioEncoder::operator=( encoder);
init( encoder.sink.get(), encoder.lowpass);
}
return *this;
}
/**
* Get the version string of the underlying faac library.
*
* @return the version string of the underlying faac library.
*/
inline const char *
getFaacVersion( void )
{
char * id;
char * copyright;
faacEncGetVersion(&id, &copyright);
return id;
}
/**
* Check wether encoding is in progress.
*
* @return true if encoding is in progress, false otherwise.
*/
inline virtual bool
isRunning ( void ) const throw ()
{
return isOpen();
}
/**
* Start encoding. This function returns as soon as possible,
* with encoding started in the background.
*
* @return true if encoding has started, false otherwise.
* @exception Exception
*/
inline virtual bool
start ( void ) throw ( Exception )
{
return open();
}
/**
* Stop encoding. Stops the encoding running in the background.
*
* @exception Exception
*/
inline virtual void
stop ( void ) throw ( Exception )
{
return close();
}
/**
* Open an encoding session.
*
* @return true if opening was successfull, false otherwise.
* @exception Exception
*/
virtual bool
open ( void ) throw ( Exception );
/**
* Check if the encoding session is open.
*
* @return true if the encoding session is open, false otherwise.
*/
inline virtual bool
isOpen ( void ) const throw ()
{
return faacOpen;
}
/**
* Check if the encoder is ready to accept data.
*
* @param sec the maximum seconds to block.
* @param usec micro seconds to block after the full seconds.
* @return true if the encoder is ready to accept data,
* false otherwise.
* @exception Exception
*/
inline virtual bool
canWrite ( unsigned int sec,
unsigned int usec ) throw ( Exception )
{
if ( !isOpen() ) {
return false;
}
return true;
}
/**
* Write data to the encoder.
* Buf is expected to be a sequence of big-endian 16 bit values,
* with left and right channels interleaved. Len is the number of
* bytes, must be a multiple of 4.
*
* @param buf the data to write.
* @param len number of bytes to write from buf.
* @return the number of bytes written (may be less than len).
* @exception Exception
*/
virtual unsigned int
write ( const void * buf,
unsigned int len ) throw ( Exception );
/**
* Flush all data that was written to the encoder to the underlying
* connection.
*
* @exception Exception
*/
virtual void
flush ( void ) throw ( Exception );
/**
* Close the encoding session.
*
* @exception Exception
*/
virtual void
close ( void ) throw ( Exception );
};
/* ================================================= external data structures */
/* ====================================================== function prototypes */
#endif /* AAC_ENCODER_H */
/*------------------------------------------------------------------------------
$Source$
$Log$
Revision 1.1 2005/04/16 21:57:34 darkeye
added AAC support through the faac codec, http://www.audiocoding.com/
------------------------------------------------------------------------------*/

View File

@ -156,6 +156,10 @@ IceCast2 :: sendLogin ( void ) throw ( Exception )
str = "application/ogg";
break;
case aac:
str = "audio/aac";
break;
default:
throw Exception( __FILE__, __LINE__,
"unsupported stream format", format);
@ -255,6 +259,9 @@ IceCast2 :: sendLogin ( void ) throw ( Exception )
$Source$
$Log$
Revision 1.12 2005/04/16 21:57:34 darkeye
added AAC support through the faac codec, http://www.audiocoding.com/
Revision 1.11 2005/04/11 18:32:32 darkeye
changed MIME type to application/ogg, which is now official

View File

@ -63,7 +63,7 @@ class IceCast2 : public CastSink
/**
* Type for specifying the format of the stream.
*/
enum StreamFormat { mp3, oggVorbis };
enum StreamFormat { mp3, oggVorbis, aac };
private:
@ -273,6 +273,9 @@ class IceCast2 : public CastSink
$Source$
$Log$
Revision 1.5 2005/04/16 21:57:34 darkeye
added AAC support through the faac codec, http://www.audiocoding.com/
Revision 1.4 2005/04/14 11:53:17 darkeye
fixed API documentation issues

View File

@ -176,6 +176,7 @@ class LameLibEncoder : public AudioEncoder, public virtual Reporter
* @param inSampleRate sample rate of the input.
* @param inBitsPerSample number of bits per sample of the input.
* @param inChannel number of channels of the input.
* @param inBigEndian shows if the input is big or little endian
* @param outBitrateMode the bit rate mode of the output.
* @param outBitrate bit rate of the output (kbits/sec).
* @param outQuality the quality of the stream.
@ -183,7 +184,6 @@ class LameLibEncoder : public AudioEncoder, public virtual Reporter
* If 0, inSampleRate is used.
* @param outChannel number of channels of the output.
* If 0, inChannel is used.
* @param inBigEndian shows if the input is big or little endian
* @param lowpass frequency threshold for the lowpass filter.
* Input above this frequency is cut.
* If 0, lame's default values are used,
@ -448,6 +448,9 @@ class LameLibEncoder : public AudioEncoder, public virtual Reporter
$Source$
$Log$
Revision 1.16 2005/04/16 21:57:34 darkeye
added AAC support through the faac codec, http://www.audiocoding.com/
Revision 1.15 2004/01/07 13:18:17 darkeye
commited patch sent by John Hay, fixing FreeBSD problems

View File

@ -1,7 +1,9 @@
bin_PROGRAMS = darkice
AM_CXXFLAGS = -O2 -pedantic -Wall @DEBUG_CXXFLAGS@ @PTHREAD_CFLAGS@ @JACK_CFLAGS@
INCLUDES = @LAME_INCFLAGS@ @VORBIS_INCFLAGS@ @ALSA_INCFLAGS@
LDADD = @PTHREAD_LIBS@ @LAME_LDFLAGS@ @VORBIS_LDFLAGS@ @ALSA_LDFLAGS@ @JACK_LIBS@
AM_CXXFLAGS = -O2 -pedantic -Wall @DEBUG_CXXFLAGS@ @PTHREAD_CFLAGS@
@JACK_CFLAGS@
INCLUDES = @LAME_INCFLAGS@ @VORBIS_INCFLAGS@ @FAAC_INCFLAGS@ @ALSA_INCFLAGS@
LDADD = @PTHREAD_LIBS@ @LAME_LDFLAGS@ @VORBIS_LDFLAGS@ @FAAC_LDFLAGS@ \
@ALSA_LDFLAGS@ @JACK_LIBS@
darkice_SOURCES = AudioEncoder.h\
AudioSource.h\
@ -32,6 +34,8 @@ darkice_SOURCES = AudioEncoder.h\
LameLibEncoder.h\
VorbisLibEncoder.cpp\
VorbisLibEncoder.h\
FaacEncoder.cpp\
FaacEncoder.h\
aflibDebug.h\
aflibDebug.cc\
aflibConverter.h\

View File

@ -296,7 +296,7 @@ VorbisLibEncoder :: write ( const void * buf,
Util::conv( bitsPerSample, b, processed, shortBuffer, isInBigEndian());
if ( converter ) {
// resample if needed
int inCount = nSamples;
@ -415,6 +415,9 @@ VorbisLibEncoder :: close ( void ) throw ( Exception )
$Source$
$Log$
Revision 1.22 2005/04/16 21:57:34 darkeye
added AAC support through the faac codec, http://www.audiocoding.com/
Revision 1.21 2005/04/11 19:26:55 darkeye
cosmetic changes
fixed warning for implicit cast from doulbe to int