make darkice compatile with the libaacplus 2.0.0 api

This commit is contained in:
rafael@riseup.net 2010-10-12 22:42:25 +00:00
parent df521d34ba
commit 99f6ff8ad7
3 changed files with 92 additions and 230 deletions

View File

@ -166,7 +166,7 @@ AC_ARG_WITH(aacplus-prefix,
if test "x${USE_AACPLUS}" = "xyes" ; then if test "x${USE_AACPLUS}" = "xyes" ; then
AC_MSG_CHECKING( [for aacplus library at ${CONFIG_AACPLUS_PREFIX}] ) 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, LA_SEARCH_LIB( AACPLUS_LIB_LOC, AACPLUS_INC_LOC, libaacplus.a libaacplus.so, aacplus.h,
${CONFIG_AACPLUS_PREFIX}) ${CONFIG_AACPLUS_PREFIX})
if test "x${AACPLUS_LIB_LOC}" != "x" ; then if test "x${AACPLUS_LIB_LOC}" != "x" ; then
AC_DEFINE( HAVE_AACPLUS_LIB, 1, [build with aacplus library] ) AC_DEFINE( HAVE_AACPLUS_LIB, 1, [build with aacplus library] )

View File

@ -76,91 +76,36 @@ aacPlusEncoder :: open ( void )
"aacplus lib opening underlying sink error"); "aacplus lib opening underlying sink error");
} }
reportEvent(1, "Using aacplus codec version", "720 3gpp"); reportEvent(1, "Using aacplus codec");
bitrate = getOutBitrate() * 1000; encoderHandle = aacplusEncOpen(getOutSampleRate(),
bandwidth = 0; getInChannel(),
useParametricStereo = 0; &inputSamples,
numAncDataBytes=0; &maxOutputBytes);
coreWriteOffset = 0;
envReadOffset = 0;
writeOffset = INPUT_DELAY*MAX_CHANNELS;
writtenSamples = 0;
aacEnc = NULL;
hEnvEnc=NULL;
/* set up basic parameters for aacPlus codec */ aacplusEncConfiguration * aacplusConfig;
AacInitDefaultConfig(&config);
nChannelsAAC = nChannelsSBR = getOutChannel();
if ( (getInChannel() == 2) && (bitrate >= 16000) && (bitrate < 44001) ) { aacplusConfig = aacplusEncGetCurrentConfiguration(encoderHandle);
useParametricStereo = 1;
nChannelsAAC = 1;
nChannelsSBR = 2;
reportEvent(10, "use Parametric Stereo"); aacplusConfig->bitRate = getOutBitrate() * 1000;
aacplusConfig->bandWidth = lowpass;
aacplusConfig->outputFormat = 1;
aacplusConfig->inputFormat = AACPLUS_INPUT_16BIT;
aacplusConfig->nChannelsOut = getOutChannel();
envReadOffset = (MAX_DS_FILTER_DELAY + INPUT_DELAY)*MAX_CHANNELS; if (!aacplusEncSetConfiguration(encoderHandle, aacplusConfig)) {
coreWriteOffset = CORE_INPUT_OFFSET_PS; throw Exception(__FILE__, __LINE__,
writeOffset = envReadOffset; "error configuring libaacplus library");
} 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 = getOutSampleRate();
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 (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;
// initialize the resampling coverter if needed // initialize the resampling coverter if needed
if ( converter ) { if ( converter ) {
#ifdef HAVE_SRC_LIB #ifdef HAVE_SRC_LIB
converterData.input_frames = 4096/((getInBitsPerSample() / 8) * getInChannel()); converterData.input_frames = 4096/((getInBitsPerSample() / 8) * getInChannel());
converterData.data_in = new float[converterData.input_frames*getInChannel()]; converterData.data_in = new float[converterData.input_frames*getInChannel()];
converterData.output_frames = (int) (converterData.input_frames * resampleRatio + 1); converterData.output_frames = (int) (converterData.input_frames * resampleRatio + 1);
if ((int) inSamples > getInChannel() * converterData.output_frames) { if ((int) inputSamples > getInChannel() * converterData.output_frames) {
resampledOffset = new float[2 * inSamples]; resampledOffset = new float[2 * inputSamples];
} else { } else {
resampledOffset = new float[2 * getInChannel() * converterData.input_frames]; resampledOffset = new float[2 * getInChannel() * converterData.input_frames];
} }
@ -178,13 +123,9 @@ aacPlusEncoder :: open ( void )
} }
aacplusOpen = true; aacplusOpen = true;
reportEvent(10, "bitrate=", bitrate); reportEvent(10, "nChannelsAAC", aacplusConfig->nChannelsOut);
reportEvent(10, "nChannelsIn", getInChannel()); reportEvent(10, "sampleRateAAC", aacplusConfig->sampleRate);
reportEvent(10, "nChannelsOut", getOutChannel()); reportEvent(10, "inSamples", inputSamples);
reportEvent(10, "nChannelsSBR", nChannelsSBR);
reportEvent(10, "nChannelsAAC", nChannelsAAC);
reportEvent(10, "sampleRateAAC", sampleRateAAC);
reportEvent(10, "inSamples", inSamples);
return true; return true;
} }
@ -203,9 +144,11 @@ aacPlusEncoder :: write ( const void * buf,
unsigned int channels = getInChannel(); unsigned int channels = getInChannel();
unsigned int bitsPerSample = getInBitsPerSample(); unsigned int bitsPerSample = getInBitsPerSample();
unsigned int sampleSize = (bitsPerSample / 8) * channels; unsigned int sampleSize = (bitsPerSample / 8) * channels;
unsigned char * b = (unsigned char*) buf;
unsigned int processed = len - (len % sampleSize); unsigned int processed = len - (len % sampleSize);
unsigned int nSamples = processed / sampleSize; unsigned int nSamples = processed / sampleSize;
unsigned int samples = (unsigned int) nSamples * channels; unsigned char * aacplusBuf = new unsigned char[maxOutputBytes];
int samples = (int) nSamples * channels;
int processedSamples = 0; int processedSamples = 0;
@ -213,7 +156,7 @@ aacPlusEncoder :: write ( const void * buf,
if ( converter ) { if ( converter ) {
unsigned int converted; unsigned int converted;
#ifdef HAVE_SRC_LIB #ifdef HAVE_SRC_LIB
src_short_to_float_array ((short *) buf, converterData.data_in, samples); src_short_to_float_array ((short *) b, converterData.data_in, samples);
converterData.input_frames = nSamples; converterData.input_frames = nSamples;
converterData.data_out = resampledOffset + (resampledOffsetSize * channels); converterData.data_out = resampledOffset + (resampledOffsetSize * channels);
int srcError = src_process (converter, &converterData); int srcError = src_process (converter, &converterData);
@ -224,7 +167,6 @@ aacPlusEncoder :: write ( const void * buf,
int inCount = nSamples; int inCount = nSamples;
short int * shortBuffer = new short int[samples]; short int * shortBuffer = new short int[samples];
int outCount = (int) (inCount * resampleRatio); int outCount = (int) (inCount * resampleRatio);
unsigned char * b = (unsigned char*) buf;
Util::conv( bitsPerSample, b, processed, shortBuffer, isInBigEndian()); Util::conv( bitsPerSample, b, processed, shortBuffer, isInBigEndian());
converted = converter->resample( inCount, converted = converter->resample( inCount,
outCount+1, outCount+1,
@ -235,18 +177,27 @@ aacPlusEncoder :: write ( const void * buf,
resampledOffsetSize += converted; resampledOffsetSize += converted;
// encode samples (if enough) // encode samples (if enough)
while(resampledOffsetSize - processedSamples >= inSamples/channels) { while(resampledOffsetSize - processedSamples >= inputSamples/channels) {
int outputBytes;
#ifdef HAVE_SRC_LIB #ifdef HAVE_SRC_LIB
short *shortData = new short[inSamples]; short *shortData = new short[inputSamples];
src_float_to_short_array(resampledOffset + (processedSamples * channels), src_float_to_short_array(resampledOffset + (processedSamples * channels),
shortData, inSamples) ; shortData, inputSamples) ;
outputBytes = aacplusEncEncode(encoderHandle,
encodeAacSamples (shortData, inSamples, channels); (int32_t*) shortData,
inputSamples,
aacplusBuf,
maxOutputBytes);
delete [] shortData; delete [] shortData;
#else #else
encodeAacSamples (&resampledOffset[processedSamples*channels], inSamples, channels); outputBytes = aacplusEncEncode(encoderHandle,
(int32_t*) &resampledOffset[processedSamples*channels],
inputSamples,
aacplusBuf,
maxOutputBytes);
#endif #endif
processedSamples+=inSamples/channels; getSink()->write(aacplusBuf, outputBytes);
processedSamples+=inputSamples/channels;
} }
if (processedSamples && (int) resampledOffsetSize >= processedSamples) { if (processedSamples && (int) resampledOffsetSize >= processedSamples) {
@ -262,72 +213,29 @@ aacPlusEncoder :: write ( const void * buf,
#endif #endif
} }
} else { } else {
encodeAacSamples ((short *) buf, samples, channels); while (processedSamples < samples) {
int outputBytes;
int inSamples = samples - processedSamples < (int) inputSamples
? samples - processedSamples
: inputSamples;
outputBytes = aacplusEncEncode(encoderHandle,
(int32_t*) (b + processedSamples/sampleSize),
inSamples,
aacplusBuf,
maxOutputBytes);
getSink()->write(aacplusBuf, outputBytes);
processedSamples += inSamples;
}
} }
delete[] aacplusBuf;
// return processedSamples;
return samples; return samples;
} }
void
aacPlusEncoder :: encodeAacSamples (short *TimeDataPcm, unsigned int samples, int channels)
throw ( Exception )
{
unsigned int i;
int ch, outSamples, numOutBytes;
for (i=0; i<samples; i++)
inBuf[(2/channels)*i+writeOffset+writtenSamples] = (float) TimeDataPcm[i];
writtenSamples+=samples;
if (writtenSamples < inSamples)
return;
/* encode one SBR frame */
EnvEncodeFrame( hEnvEnc,
inBuf + envReadOffset,
inBuf + coreWriteOffset,
MAX_CHANNELS,
&numAncDataBytes,
ancDataBytes);
/* 2:1 downsampling for AAC core */
if (!useParametricStereo) {
for( ch=0; ch<nChannelsAAC; ch++ )
IIR21_Downsample( &(IIR21_reSampler[ch]),
inBuf + writeOffset+ch,
writtenSamples/channels,
MAX_CHANNELS,
inBuf+ch,
&outSamples,
MAX_CHANNELS);
}
/* encode one AAC frame */
AacEncEncode( aacEnc,
inBuf,
useParametricStereo ? 1 : MAX_CHANNELS, /* stride (step) */
ancDataBytes,
&numAncDataBytes,
(unsigned *) (outBuf+ADTS_HEADER_SIZE),
&numOutBytes);
if (useParametricStereo) {
memcpy( inBuf,inBuf+AACENC_BLOCKSIZE,CORE_INPUT_OFFSET_PS*sizeof(float));
} else {
memmove( inBuf,inBuf+AACENC_BLOCKSIZE*2*MAX_CHANNELS,writeOffset*sizeof(float));
}
/* Write one frame of encoded audio */
if (numOutBytes) {
adts_hdr_up(outBuf, numOutBytes);
sink->write(outBuf, numOutBytes+ADTS_HEADER_SIZE);
}
writtenSamples=0;
return;
}
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Flush the data from the encoder * Flush the data from the encoder
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
@ -352,12 +260,7 @@ aacPlusEncoder :: close ( void ) throw ( Exception )
if ( isOpen() ) { if ( isOpen() ) {
flush(); flush();
destroy_plans(); aacplusEncClose(encoderHandle);
AacEncClose(aacEnc);
if (hEnvEnc) {
EnvClose(hEnvEnc);
}
aacplusOpen = false; aacplusOpen = false;
sink->close(); sink->close();

View File

@ -41,18 +41,7 @@
#endif #endif
#ifdef HAVE_AACPLUS_LIB #ifdef HAVE_AACPLUS_LIB
extern "C" { #include <aacplus.h>
#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 #else
#error configure with aacplus #error configure with aacplus
#endif #endif
@ -87,12 +76,6 @@ extern "C" {
* @version $Revision$ * @version $Revision$
*/ */
#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 class aacPlusEncoder : public AudioEncoder, public virtual Reporter
{ {
private: private:
@ -124,31 +107,26 @@ class aacPlusEncoder : public AudioEncoder, public virtual Reporter
*/ */
Ref<Sink> sink; 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]; * The handle to the AAC+ encoder instance.
IIR21_RESAMPLER IIR21_reSampler[MAX_CHANNELS]; */
aacplusEncHandle encoderHandle;
AACENC_CONFIG config; /**
* The maximum number of input samples to supply to the encoder.
*/
unsigned long inputSamples;
int nChannelsAAC, nChannelsSBR; /**
unsigned int sampleRateAAC; * The maximum number of output bytes the encoder returns in one call.
*/
unsigned long maxOutputBytes;
int bitrate; /**
int bandwidth; * Lowpass filter. Sound frequency in Hz, from where up the
* input is cut.
unsigned int numAncDataBytes; */
unsigned char ancDataBytes[MAX_PAYLOAD_SIZE]; int lowpass;
bool useParametricStereo;
int coreWriteOffset;
int envReadOffset;
int writeOffset;
struct AAC_ENCODER *aacEnc;
unsigned int inSamples;
unsigned int writtenSamples;
HANDLE_SBR_ENCODER hEnvEnc;
sbrConfiguration sbrConfig;
/** /**
* Initialize the object. * Initialize the object.
@ -157,10 +135,11 @@ class aacPlusEncoder : public AudioEncoder, public virtual Reporter
* @exception Exception * @exception Exception
*/ */
inline void inline void
init ( Sink * sink) throw (Exception) init ( Sink * sink, int lowpass) throw (Exception)
{ {
this->aacplusOpen = false; this->aacplusOpen = false;
this->sink = sink; this->sink = sink;
this->lowpass = lowpass;
/* TODO: if we have float as input, we don't need conversion */ /* TODO: if we have float as input, we don't need conversion */
if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 32 ) { if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 32 ) {
@ -179,11 +158,6 @@ class aacPlusEncoder : public AudioEncoder, public virtual Reporter
"unsupported number of output channels for the encoder", "unsupported number of output channels for the encoder",
getOutChannel() ); 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");
}
if ( getOutSampleRate() == getInSampleRate() ) { if ( getOutSampleRate() == getInSampleRate() ) {
resampleRatio = 1; resampleRatio = 1;
@ -237,17 +211,6 @@ class aacPlusEncoder : public AudioEncoder, public virtual Reporter
"specified bits per sample with samplerate conversion not supported", "specified bits per sample with samplerate conversion not supported",
getInBitsPerSample() ); getInBitsPerSample() );
} }
bitrate = getOutBitrate() * 1000;
bandwidth = 0;
useParametricStereo = 0;
numAncDataBytes=0;
coreWriteOffset = 0;
envReadOffset = 0;
writeOffset = INPUT_DELAY*MAX_CHANNELS;
writtenSamples = 0;
aacEnc = NULL;
hEnvEnc=NULL;
} }
/** /**
@ -269,10 +232,6 @@ class aacPlusEncoder : public AudioEncoder, public virtual Reporter
} }
} }
void
encodeAacSamples (short *TimeDataPcm, unsigned int samples, int channels)
throw ( Exception );
protected: protected:
/** /**
@ -335,7 +294,7 @@ class aacPlusEncoder : public AudioEncoder, public virtual Reporter
outSampleRate, outSampleRate,
outChannel ) outChannel )
{ {
init( sink); init( sink, lowpass);
} }
/** /**
@ -376,7 +335,7 @@ class aacPlusEncoder : public AudioEncoder, public virtual Reporter
outSampleRate, outSampleRate,
outChannel ) outChannel )
{ {
init( sink); init( sink, lowpass );
} }
/** /**
@ -389,7 +348,7 @@ class aacPlusEncoder : public AudioEncoder, public virtual Reporter
throw ( Exception ) throw ( Exception )
: AudioEncoder( encoder ) : AudioEncoder( encoder )
{ {
init( encoder.sink.get()); init( encoder.sink.get(), encoder.lowpass);
} }
@ -420,7 +379,7 @@ class aacPlusEncoder : public AudioEncoder, public virtual Reporter
if ( this != &encoder ) { if ( this != &encoder ) {
strip(); strip();
AudioEncoder::operator=( encoder); AudioEncoder::operator=( encoder);
init( encoder.sink.get()); init( encoder.sink.get(), encoder.lowpass);
} }
return *this; return *this;