added aac+ encoding support, re #2
This commit is contained in:
parent
d9aa3f0753
commit
2a98f1f03b
|
@ -149,6 +149,42 @@ else
|
|||
fi
|
||||
|
||||
|
||||
dnl-----------------------------------------------------------------------------
|
||||
dnl link the aacplus library if requested
|
||||
dnl-----------------------------------------------------------------------------
|
||||
AC_SUBST(AACPLUS_INCFLAGS)
|
||||
AC_SUBST(AACPLUS_LDFLAGS)
|
||||
|
||||
AC_ARG_WITH(aacplus,
|
||||
[ --with-aacplus use aacplus for encoding AAC HEv2 streams [yes] ],
|
||||
USE_AACPLUS=${withval}, USE_AACPLUS="yes" )
|
||||
AC_ARG_WITH(aacplus-prefix,
|
||||
[ --with-aacplus-prefix=DIR alternate location for aacplus [/usr]
|
||||
look for libraries in AACPLUS-PREFIX/lib,
|
||||
for headers in AACPLUS-PREFIX/include],
|
||||
CONFIG_AACPLUS_PREFIX="${withval}", CONFIG_AACPLUS_PREFIX="/usr")
|
||||
|
||||
if test "x${USE_AACPLUS}" = "xyes" ; then
|
||||
AC_MSG_CHECKING( [for aacplus library at ${CONFIG_AACPLUS_PREFIX}] )
|
||||
LA_SEARCH_LIB( AACPLUS_LIB_LOC, AACPLUS_INC_LOC, libaacplus.a libaacplus.so, sbr_main.h,
|
||||
${CONFIG_AACPLUS_PREFIX})
|
||||
if test "x${AACPLUS_LIB_LOC}" != "x" ; then
|
||||
AC_DEFINE( HAVE_AACPLUS_LIB, 1, [build with aacplus library] )
|
||||
if test "x${AACPLUS_INC_LOC}" != "x${SYSTEM_INCLUDE}" ; then
|
||||
AACPLUS_INCFLAGS="-I${AACPLUS_INC_LOC}"
|
||||
fi
|
||||
AACPLUS_LDFLAGS="-L${AACPLUS_LIB_LOC} -laacplus"
|
||||
# TODO: we have to define _FFTW3 only if libaacplus builded with fftw3f
|
||||
AC_DEFINE( _FFTW3, 1, [libaacplus have to be builded with fftw3f library] )
|
||||
AC_MSG_RESULT( [found at ${CONFIG_AACPLUS_PREFIX}] )
|
||||
else
|
||||
AC_MSG_WARN( [not found, building without aacplus])
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT( [building without aacplus] )
|
||||
fi
|
||||
|
||||
|
||||
dnl-----------------------------------------------------------------------------
|
||||
dnl link the twolame library if requested
|
||||
dnl-----------------------------------------------------------------------------
|
||||
|
@ -189,8 +225,9 @@ dnl-----------------------------------------------------------------------------
|
|||
if test "x${LAME_LDFLAGS}" = "x" \
|
||||
-a "x${VORBIS_LDFLAGS}" = "x" \
|
||||
-a "x${FAAC_LDFLAGS}" = "x" \
|
||||
-a "x${AACPLUS_LDFLAGS}" = "x" \
|
||||
-a "x${TWOLAME_LDFLAGS}" = "x"; then
|
||||
AC_MSG_ERROR([neither lame, Ogg Vorbis, faac nor twolame configured])
|
||||
AC_MSG_ERROR([neither lame, Ogg Vorbis, faac, aac+ nor twolame configured])
|
||||
fi
|
||||
|
||||
|
||||
|
|
|
@ -96,6 +96,10 @@
|
|||
#include "FaacEncoder.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AACPLUS_LIB
|
||||
#include "aacPlusEncoder.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* =================================================== local data structures */
|
||||
|
||||
|
@ -454,6 +458,8 @@ DarkIce :: configIceCast2 ( const Config & config,
|
|||
format = IceCast2::mp2;
|
||||
} else if ( Util::strEq( str, "aac") ) {
|
||||
format = IceCast2::aac;
|
||||
} else if ( Util::strEq( str, "aacp") ) {
|
||||
format = IceCast2::aacp;
|
||||
} else {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"unsupported stream format: ", str);
|
||||
|
@ -643,6 +649,24 @@ DarkIce :: configIceCast2 ( const Config & config,
|
|||
#endif // HAVE_FAAC_LIB
|
||||
break;
|
||||
|
||||
case IceCast2::aacp:
|
||||
#ifndef HAVE_AACPLUS_LIB
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"DarkIce not compiled with AAC+ support, "
|
||||
"thus can't aacp stream: ",
|
||||
stream);
|
||||
#else
|
||||
audioOuts[u].encoder = new aacPlusEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
dsp->getChannel());
|
||||
#endif // HAVE_AACPLUS_LIB
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"Illegal stream format: ", format);
|
||||
|
@ -878,7 +902,8 @@ DarkIce :: configFileCast ( const Config & config )
|
|||
if ( !Util::strEq( format, "vorbis")
|
||||
&& !Util::strEq( format, "mp3")
|
||||
&& !Util::strEq( format, "mp2")
|
||||
&& !Util::strEq( format, "aac") ) {
|
||||
&& !Util::strEq( format, "aac")
|
||||
&& !Util::strEq( format, "aacp") ) {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"unsupported stream format: ", format);
|
||||
}
|
||||
|
@ -936,6 +961,12 @@ DarkIce :: configFileCast ( const Config & config )
|
|||
"average bitrate mode");
|
||||
}
|
||||
|
||||
if (Util::strEq(format, "aacp") && bitrateMode != AudioEncoder::cbr) {
|
||||
throw Exception(__FILE__, __LINE__,
|
||||
"currently the AAC+ format only supports "
|
||||
"constant bitrate mode");
|
||||
}
|
||||
|
||||
str = cs->get( "lowpass");
|
||||
lowpass = str ? Util::strToL( str) : 0;
|
||||
str = cs->get( "highpass");
|
||||
|
@ -1031,6 +1062,22 @@ DarkIce :: configFileCast ( const Config & config )
|
|||
sampleRate,
|
||||
dsp->getChannel());
|
||||
#endif // HAVE_FAAC_LIB
|
||||
} else if ( Util::strEq( format, "aacp") ) {
|
||||
#ifndef HAVE_AACPLUS_LIB
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"DarkIce not compiled with AAC+ support, "
|
||||
"thus can't aacplus stream: ",
|
||||
stream);
|
||||
#else
|
||||
audioOuts[u].encoder = new aacPlusEncoder(
|
||||
audioOuts[u].server.get(),
|
||||
dsp.get(),
|
||||
bitrateMode,
|
||||
bitrate,
|
||||
quality,
|
||||
sampleRate,
|
||||
dsp->getChannel());
|
||||
#endif // HAVE_AACPLUS_LIB
|
||||
} else {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"Illegal stream format: ", format);
|
||||
|
|
|
@ -161,6 +161,10 @@ IceCast2 :: sendLogin ( void ) throw ( Exception )
|
|||
str = "audio/aac";
|
||||
break;
|
||||
|
||||
case aacp:
|
||||
str = "audio/aacp";
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"unsupported stream format", format);
|
||||
|
|
|
@ -63,7 +63,7 @@ class IceCast2 : public CastSink
|
|||
/**
|
||||
* Type for specifying the format of the stream.
|
||||
*/
|
||||
enum StreamFormat { mp3, mp2, oggVorbis, aac };
|
||||
enum StreamFormat { mp3, mp2, oggVorbis, aac, aacp };
|
||||
|
||||
|
||||
private:
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
bin_PROGRAMS = darkice
|
||||
AM_CXXFLAGS = -O2 -pedantic -Wall @DEBUG_CXXFLAGS@ @PTHREAD_CFLAGS@
|
||||
@JACK_CFLAGS@
|
||||
INCLUDES = @LAME_INCFLAGS@ @VORBIS_INCFLAGS@ @FAAC_INCFLAGS@ @TWOLAME_INCFLAGS@ @ALSA_INCFLAGS@
|
||||
LDADD = @PTHREAD_LIBS@ @LAME_LDFLAGS@ @VORBIS_LDFLAGS@ @FAAC_LDFLAGS@ @TWOLAME_LDFLAGS@ \
|
||||
INCLUDES = @LAME_INCFLAGS@ @VORBIS_INCFLAGS@ @FAAC_INCFLAGS@ @AACPLUS_INCFLAGS@ @TWOLAME_INCFLAGS@ @ALSA_INCFLAGS@
|
||||
LDADD = @PTHREAD_LIBS@ @LAME_LDFLAGS@ @VORBIS_LDFLAGS@ @FAAC_LDFLAGS@ @AACPLUS_LDFLAGS@ @TWOLAME_LDFLAGS@ \
|
||||
@ALSA_LDFLAGS@ @JACK_LDFLAGS@
|
||||
|
||||
darkice_SOURCES = AudioEncoder.h\
|
||||
|
@ -38,6 +38,8 @@ darkice_SOURCES = AudioEncoder.h\
|
|||
VorbisLibEncoder.h\
|
||||
FaacEncoder.cpp\
|
||||
FaacEncoder.h\
|
||||
aacPlusEncoder.cpp\
|
||||
aacPlusEncoder.h\
|
||||
aflibDebug.h\
|
||||
aflibDebug.cc\
|
||||
aflibConverter.h\
|
||||
|
|
|
@ -0,0 +1,309 @@
|
|||
/*------------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2005 Tyrell Corporation. All rights reserved.
|
||||
|
||||
Tyrell DarkIce
|
||||
|
||||
File : aacPlusEncoder.cpp
|
||||
Version : $Revision: 0.2 $
|
||||
Author : $Author: tipok $
|
||||
Location : $Source: /darkice-aacplus/src/aacPlusEncoder.cpp,v $
|
||||
|
||||
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 aacplus support configured in
|
||||
#ifdef HAVE_AACPLUS_LIB
|
||||
|
||||
|
||||
|
||||
#include "Exception.h"
|
||||
#include "Util.h"
|
||||
#include "aacPlusEncoder.h"
|
||||
|
||||
|
||||
/* =================================================== local data structures */
|
||||
|
||||
|
||||
/* ================================================ local constants & macros */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* File identity
|
||||
*----------------------------------------------------------------------------*/
|
||||
static const char fileid[] = "$Id: aacPlusEncoder.cpp,v 0.2 2005/04/16 22:19:20 klaus Exp $";
|
||||
|
||||
|
||||
/* =============================================== local function prototypes */
|
||||
|
||||
|
||||
/* ============================================================= module code */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Open an encoding session
|
||||
*----------------------------------------------------------------------------*/
|
||||
bool
|
||||
aacPlusEncoder :: open ( void )
|
||||
throw ( Exception )
|
||||
{
|
||||
if ( isOpen() ) {
|
||||
close();
|
||||
}
|
||||
|
||||
// open the underlying sink
|
||||
if ( !sink->open() ) {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"aacplus lib opening underlying sink error");
|
||||
}
|
||||
|
||||
reportEvent(1, "Using aacplus codec version", "720 3gpp");
|
||||
|
||||
|
||||
/* set up basic parameters for aacPlus codec */
|
||||
AacInitDefaultConfig(&config);
|
||||
nChannelsAAC = nChannelsSBR = getOutChannel();
|
||||
|
||||
if ( (getInChannel() == 2) && (bitrate >= 16000) && (bitrate < 44001) ) {
|
||||
useParametricStereo = 1;
|
||||
nChannelsAAC = 1;
|
||||
nChannelsSBR = 2;
|
||||
|
||||
reportEvent(10, "use Parametric Stereo");
|
||||
|
||||
envReadOffset = (MAX_DS_FILTER_DELAY + INPUT_DELAY)*MAX_CHANNELS;
|
||||
coreWriteOffset = CORE_INPUT_OFFSET_PS;
|
||||
writeOffset = envReadOffset;
|
||||
} else {
|
||||
/* set up 2:1 downsampling */
|
||||
InitIIR21_Resampler(&(IIR21_reSampler[0]));
|
||||
InitIIR21_Resampler(&(IIR21_reSampler[1]));
|
||||
|
||||
if(IIR21_reSampler[0].delay > MAX_DS_FILTER_DELAY){
|
||||
throw Exception(__FILE__, __LINE__, "IIR21 resampler delay is bigger then MAX_DS_FILTER_DELAY");
|
||||
}
|
||||
writeOffset += IIR21_reSampler[0].delay*MAX_CHANNELS;
|
||||
}
|
||||
|
||||
sampleRateAAC = getInSampleRate();
|
||||
config.bitRate = bitrate;
|
||||
config.nChannelsIn=getInChannel();
|
||||
config.nChannelsOut=nChannelsAAC;
|
||||
config.bandWidth=bandwidth;
|
||||
|
||||
/* set up SBR configuration */
|
||||
if(!IsSbrSettingAvail (bitrate, nChannelsAAC, sampleRateAAC, &sampleRateAAC)) {
|
||||
throw Exception(__FILE__, __LINE__, "No valid SBR configuration found");
|
||||
}
|
||||
|
||||
InitializeSbrDefaults (&sbrConfig);
|
||||
sbrConfig.usePs = useParametricStereo;
|
||||
|
||||
AdjustSbrSettings( &sbrConfig,
|
||||
bitrate,
|
||||
nChannelsAAC,
|
||||
sampleRateAAC,
|
||||
AACENC_TRANS_FAC,
|
||||
24000);
|
||||
|
||||
EnvOpen( &hEnvEnc,
|
||||
inBuf + coreWriteOffset,
|
||||
&sbrConfig,
|
||||
&config.bandWidth);
|
||||
|
||||
/* set up AAC encoder, now that samling rate is known */
|
||||
config.sampleRate = sampleRateAAC;
|
||||
if ((error = AacEncOpen(&aacEnc, config)) != 0){
|
||||
AacEncClose(aacEnc);
|
||||
throw Exception(__FILE__, __LINE__, "Initialisation of AAC failed !");
|
||||
}
|
||||
|
||||
init_plans();
|
||||
|
||||
/* create the ADTS header */
|
||||
adts_hdr(outBuf, &config);
|
||||
|
||||
inSamples = AACENC_BLOCKSIZE * getInChannel() * 2;
|
||||
|
||||
aacplusOpen = true;
|
||||
reportEvent(10, "bitrate=", bitrate);
|
||||
reportEvent(10, "nChannelsIn", getInChannel());
|
||||
reportEvent(10, "nChannelsSBR", nChannelsSBR);
|
||||
reportEvent(10, "nChannelsOut", nChannelsAAC);
|
||||
reportEvent(10, "sampleRateAAC", sampleRateAAC);
|
||||
reportEvent(10, "inSamples", inSamples);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Write data to the encoder
|
||||
*----------------------------------------------------------------------------*/
|
||||
unsigned int
|
||||
aacPlusEncoder :: 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 int processed = len - (len % sampleSize);
|
||||
unsigned int nSamples = processed / sampleSize;
|
||||
int samples = (int) nSamples * channels;
|
||||
|
||||
|
||||
|
||||
|
||||
int i;
|
||||
int ch, outSamples, numOutBytes;
|
||||
|
||||
|
||||
reportEvent(10, "converting short to float");
|
||||
short *TimeDataPcm = (short *) buf;
|
||||
for (i=0; i<samples; i++)
|
||||
inBuf[i+writeOffset+writtenSamples] = (float) TimeDataPcm[i];
|
||||
writtenSamples+=samples;
|
||||
reportEvent(10, "writtenSamples", writtenSamples);
|
||||
if (writtenSamples < inSamples)
|
||||
return samples;
|
||||
|
||||
/* encode one SBR frame */
|
||||
reportEvent(10, "encode one SBR frame");
|
||||
EnvEncodeFrame( hEnvEnc,
|
||||
inBuf + envReadOffset,
|
||||
inBuf + coreWriteOffset,
|
||||
MAX_CHANNELS,
|
||||
&numAncDataBytes,
|
||||
ancDataBytes);
|
||||
|
||||
reportEvent(10, "numAncDataBytes=", numAncDataBytes);
|
||||
|
||||
/* 2:1 downsampling for AAC core */
|
||||
if (!useParametricStereo){
|
||||
reportEvent(10, "2:1 downsampling for AAC core");
|
||||
for( ch=0; ch<nChannelsAAC; ch++ )
|
||||
IIR21_Downsample( &(IIR21_reSampler[ch]),
|
||||
inBuf+writeOffset+ch,
|
||||
writtenSamples/getInChannel(),
|
||||
MAX_CHANNELS,
|
||||
inBuf+ch,
|
||||
&outSamples,
|
||||
MAX_CHANNELS);
|
||||
reportEvent(10, "outSamples=", outSamples);
|
||||
}
|
||||
|
||||
/* encode one AAC frame */
|
||||
if (hEnvEnc && useParametricStereo) {
|
||||
reportEvent(10, "Parametric Stereo encode one AAC frame");
|
||||
AacEncEncode( aacEnc,
|
||||
inBuf,
|
||||
1, /* stride (step) */
|
||||
ancDataBytes,
|
||||
&numAncDataBytes,
|
||||
(unsigned *) (outBuf+ADTS_HEADER_SIZE),
|
||||
&numOutBytes);
|
||||
|
||||
if(hEnvEnc)
|
||||
memcpy( inBuf,inBuf+AACENC_BLOCKSIZE,CORE_INPUT_OFFSET_PS*sizeof(float));
|
||||
|
||||
} else {
|
||||
reportEvent(10, "encode one AAC frame");
|
||||
AacEncEncode( aacEnc,
|
||||
inBuf+coreReadOffset,
|
||||
MAX_CHANNELS,
|
||||
ancDataBytes,
|
||||
&numAncDataBytes,
|
||||
(unsigned *) (outBuf+ADTS_HEADER_SIZE),
|
||||
&numOutBytes);
|
||||
|
||||
reportEvent(10, "done AAC=", numOutBytes);
|
||||
if(hEnvEnc)
|
||||
memmove( inBuf,inBuf+AACENC_BLOCKSIZE*2*MAX_CHANNELS,writeOffset*sizeof(float));
|
||||
}
|
||||
|
||||
/* Write one frame of encoded audio */
|
||||
if (numOutBytes) {
|
||||
reportEvent(10, "Write one frame of encoded audio:", numOutBytes+ADTS_HEADER_SIZE);
|
||||
adts_hdr_up(outBuf, numOutBytes);
|
||||
sink->write(outBuf, numOutBytes+ADTS_HEADER_SIZE);
|
||||
}
|
||||
writtenSamples=0;
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Flush the data from the encoder
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
aacPlusEncoder :: flush ( void )
|
||||
throw ( Exception )
|
||||
{
|
||||
if ( !isOpen() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
sink->flush();
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Close the encoding session
|
||||
*----------------------------------------------------------------------------*/
|
||||
void
|
||||
aacPlusEncoder :: close ( void ) throw ( Exception )
|
||||
{
|
||||
if ( isOpen() ) {
|
||||
flush();
|
||||
|
||||
destroy_plans();
|
||||
AacEncClose(aacEnc);
|
||||
if (hEnvEnc) {
|
||||
EnvClose(hEnvEnc);
|
||||
}
|
||||
|
||||
aacplusOpen = false;
|
||||
|
||||
sink->close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // HAVE_AACPLUS_LIB
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
|
||||
$Source: /cvsroot/darkice/darkice/src/aacPlusEncoder.cpp,v $
|
||||
|
||||
$Log: aacPlusEncoder.cpp,v $
|
||||
Revision 0.1 2005/04/16 21:57:34 klaus
|
||||
added AAC support through the aacplus codec, http://www.audiocoding.com/
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------------------*/
|
||||
|
|
@ -0,0 +1,477 @@
|
|||
/*------------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
|
||||
|
||||
Tyrell DarkIce
|
||||
|
||||
File : aacPlusEncoder.h
|
||||
Version : $Revision: 0.2 $
|
||||
Author : $Author: tipok $
|
||||
Location : $HeadURL$
|
||||
|
||||
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 AACP_ENCODER_H
|
||||
#define AACP_ENCODER_H
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error This is a C++ include file
|
||||
#endif
|
||||
|
||||
|
||||
/* ============================================================ include files */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AACPLUS_LIB
|
||||
extern "C" {
|
||||
#include <libaacplus/cfftn.h>
|
||||
#include <libaacplus/FloatFR.h>
|
||||
#include <libaacplus/aacenc.h>
|
||||
#include <libaacplus/resampler.h>
|
||||
|
||||
#include <libaacplus/adts.h>
|
||||
|
||||
#include <libaacplus/sbr_main.h>
|
||||
#include <libaacplus/aac_ram.h>
|
||||
#include <libaacplus/aac_rom.h>
|
||||
}
|
||||
#else
|
||||
#error configure with aacplus
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include "Ref.h"
|
||||
#include "Exception.h"
|
||||
#include "Reporter.h"
|
||||
#include "AudioEncoder.h"
|
||||
#include "Sink.h"
|
||||
|
||||
|
||||
/* ================================================================ constants */
|
||||
|
||||
|
||||
/* =================================================================== macros */
|
||||
|
||||
|
||||
/* =============================================================== data types */
|
||||
|
||||
/**
|
||||
* A class representing aacplus AAC+ encoder.
|
||||
*
|
||||
* @author $Author: tipok $
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
|
||||
#define CORE_DELAY (1600)
|
||||
#define INPUT_DELAY ((CORE_DELAY)*2 +6*64-2048+1) /* ((1600 (core codec)*2 (multi rate) + 6*64 (sbr dec delay) - 2048 (sbr enc delay) + magic*/
|
||||
#define MAX_DS_FILTER_DELAY 16 /* the additional max resampler filter delay (source fs)*/
|
||||
|
||||
#define CORE_INPUT_OFFSET_PS (0) /* (96-64) makes AAC still some 64 core samples too early wrt SBR ... maybe -32 would be even more correct, but 1024-32 would need additional SBR bitstream delay by one frame */
|
||||
|
||||
class aacPlusEncoder : public AudioEncoder, public virtual Reporter
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* A flag to indicate if the encoding session is open.
|
||||
*/
|
||||
bool aacplusOpen;
|
||||
|
||||
/**
|
||||
* The Sink to dump aac+ data to
|
||||
*/
|
||||
Ref<Sink> sink;
|
||||
|
||||
float inBuf[(AACENC_BLOCKSIZE*2 + MAX_DS_FILTER_DELAY + INPUT_DELAY)*MAX_CHANNELS];
|
||||
char outBuf[(6144/8)*MAX_CHANNELS+ADTS_HEADER_SIZE];
|
||||
IIR21_RESAMPLER IIR21_reSampler[MAX_CHANNELS];
|
||||
|
||||
AACENC_CONFIG config;
|
||||
|
||||
int error;
|
||||
int nChannelsAAC, nChannelsSBR;
|
||||
unsigned int sampleRateAAC;
|
||||
int bitrate;
|
||||
int bandwidth;
|
||||
|
||||
unsigned int numAncDataBytes;
|
||||
unsigned char ancDataBytes[MAX_PAYLOAD_SIZE];
|
||||
|
||||
int numSamplesRead;
|
||||
int useParametricStereo;
|
||||
int coreWriteOffset;
|
||||
int coreReadOffset;
|
||||
int envReadOffset;
|
||||
int writeOffset;
|
||||
struct AAC_ENCODER *aacEnc;
|
||||
unsigned int inSamples;
|
||||
unsigned int writtenSamples;
|
||||
|
||||
HANDLE_SBR_ENCODER hEnvEnc;
|
||||
sbrConfiguration sbrConfig;
|
||||
|
||||
/**
|
||||
* Initialize the object.
|
||||
*
|
||||
* @param sink the sink to send mp3 output to
|
||||
* @exception Exception
|
||||
*/
|
||||
inline void
|
||||
init ( Sink * sink) throw (Exception)
|
||||
{
|
||||
this->aacplusOpen = false;
|
||||
this->sink = sink;
|
||||
|
||||
/* TODO: if we have float as input, we don't need conversion */
|
||||
if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 32 ) {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"specified bits per sample not supported",
|
||||
getInBitsPerSample() );
|
||||
}
|
||||
|
||||
if ( getInChannel() != 2 ) {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"unsupported number of input channels for the encoder",
|
||||
getInChannel() );
|
||||
}
|
||||
if ( getOutChannel() != 2 ) {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"unsupported number of output channels for the encoder",
|
||||
getOutChannel() );
|
||||
}
|
||||
/* TODO: this will be neede when we implement mono aac+ encoding */
|
||||
if ( getInChannel() != getOutChannel() ) {
|
||||
throw Exception( __FILE__, __LINE__,
|
||||
"input channels and output channels do not match");
|
||||
}
|
||||
|
||||
bitrate = getOutBitrate() * 1000;
|
||||
bandwidth = 0;
|
||||
useParametricStereo = 0;
|
||||
numAncDataBytes=0;
|
||||
coreWriteOffset = 0;
|
||||
coreReadOffset = 0;
|
||||
envReadOffset = 0;
|
||||
writeOffset = INPUT_DELAY*MAX_CHANNELS;
|
||||
writtenSamples = 0;
|
||||
aacEnc = NULL;
|
||||
hEnvEnc=NULL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* De-initialize the object.
|
||||
*
|
||||
* @exception Exception
|
||||
*/
|
||||
inline void
|
||||
strip ( void ) throw ( Exception )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Default constructor. Always throws an Exception.
|
||||
*
|
||||
* @exception Exception
|
||||
*/
|
||||
inline
|
||||
aacPlusEncoder ( 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, aacplus's default values are used,
|
||||
* which depends on the out sample rate.
|
||||
* @exception Exception
|
||||
*/
|
||||
inline
|
||||
aacPlusEncoder ( 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 ( sink,
|
||||
inSampleRate,
|
||||
inBitsPerSample,
|
||||
inChannel,
|
||||
inBigEndian,
|
||||
outBitrateMode,
|
||||
outBitrate,
|
||||
outQuality,
|
||||
outSampleRate,
|
||||
outChannel )
|
||||
{
|
||||
init( sink);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, aacplus's default values are used,
|
||||
* which depends on the out sample rate.
|
||||
* @exception Exception
|
||||
*/
|
||||
inline
|
||||
aacPlusEncoder ( 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 ( sink,
|
||||
as,
|
||||
outBitrateMode,
|
||||
outBitrate,
|
||||
outQuality,
|
||||
outSampleRate,
|
||||
outChannel )
|
||||
{
|
||||
init( sink);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*
|
||||
* @param encoder the aacPlusEncoder to copy.
|
||||
*/
|
||||
inline
|
||||
aacPlusEncoder ( const aacPlusEncoder & encoder )
|
||||
throw ( Exception )
|
||||
: AudioEncoder( encoder )
|
||||
{
|
||||
init( encoder.sink.get());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*
|
||||
* @exception Exception
|
||||
*/
|
||||
inline virtual
|
||||
~aacPlusEncoder ( void ) throw ( Exception )
|
||||
{
|
||||
if ( isOpen() ) {
|
||||
close();
|
||||
}
|
||||
strip();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assignment operator.
|
||||
*
|
||||
* @param encoder the aacPlusEncoder to assign this to.
|
||||
* @return a reference to this aacPlusEncoder.
|
||||
* @exception Exception
|
||||
*/
|
||||
inline virtual aacPlusEncoder &
|
||||
operator= ( const aacPlusEncoder & encoder ) throw ( Exception )
|
||||
{
|
||||
if ( this != &encoder ) {
|
||||
strip();
|
||||
AudioEncoder::operator=( encoder);
|
||||
init( encoder.sink.get());
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version string of the underlying aacplus library.
|
||||
*
|
||||
* @return the version string of the underlying aacplus library.
|
||||
*/
|
||||
inline const char *
|
||||
getAacPlusVersion( void )
|
||||
{
|
||||
char * id;
|
||||
//char * copyright;
|
||||
|
||||
/* aacplusEncGetVersion(&id, ©right); */
|
||||
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 aacplusOpen;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 /* AACP_ENCODER_H */
|
||||
|
Loading…
Reference in New Issue