📄 audiosourcedecoder.cpp
字号:
const _REAL rAtt = (_REAL) i / iResOutBlockSize;
vecTempResBufOutCurLeft[i] *= rAtt;
vecTempResBufOutCurRight[i] *= rAtt;
if (bUseReverbEffect == TRUE)
{
/* Cross-fade reverberation effect */
const _REAL rRevSam = (1.0 - rAtt) * AudioRev.
ProcessSample(0, 0);
/* Mono reverberation signal */
vecTempResBufOutCurLeft[i] += rRevSam;
vecTempResBufOutCurRight[i] += rRevSam;
}
}
/* Reset flag */
bAudioWasOK = TRUE;
}
}
/* Conversion from _REAL to _SAMPLE with special function */
for (i = 0; i < iResOutBlockSize; i++)
{
(*pvecOutputData)[iOutputBlockSize + i * 2] =
Real2Sample(vecTempResBufOutOldLeft[i]); /* Left channel */
(*pvecOutputData)[iOutputBlockSize + i * 2 + 1] =
Real2Sample(vecTempResBufOutOldRight[i]); /* Right channel */
}
/* Add new block to output block size ("* 2" for stereo output block) */
iOutputBlockSize += iResOutBlockSize * 2;
/* Store current audio block */
for (i = 0; i < iResOutBlockSize; i++)
{
vecTempResBufOutOldLeft[i] = vecTempResBufOutCurLeft[i];
vecTempResBufOutOldRight[i] = vecTempResBufOutCurRight[i];
}
}
#endif
}
void CAudioSourceDecoder::InitInternal(CParameter& ReceiverParam)
{
/*
Since we use the exception mechanism in this init routine, the sequence of
the individual initializations is very important!
Requirement for text message is "stream is used" and "audio service".
Requirement for AAC decoding are the requirements above plus "audio coding
is AAC"
*/
int iCurAudioStreamID;
int iMaxLenResamplerOutput;
int iCurSelServ;
int iDRMchanMode;
int iAudioSampleRate;
int iAACSampleRate;
int iLenAudHigh;
int iNumHeaderBytes;
try
{
/* Init error flags and output block size parameter. The output block
size is set in the processing routine. We must set it here in case
of an error in the initialization, this part in the processing
routine is not being called */
DoNotProcessAAC = FALSE;
DoNotProcessData = FALSE;
iOutputBlockSize = 0;
/* Init counter for correctly decoded audio blocks */
iNumCorDecAudio = 0;
/* Get number of total input bits for this module */
iInputBlockSize = ReceiverParam.iNumAudioDecoderBits;
/* Get current selected audio service */
iCurSelServ = ReceiverParam.GetCurSelAudioService();
/* Current audio stream ID */
iCurAudioStreamID =
ReceiverParam.Service[iCurSelServ].AudioParam.iStreamID;
/* The requirement for this module is that the stream is used and the
service is an audio service. Check it here */
if ((ReceiverParam.Service[iCurSelServ].
eAudDataFlag != CParameter::SF_AUDIO) ||
(iCurAudioStreamID == STREAM_ID_NOT_USED))
{
throw CInitErr(ET_ALL);
}
/* Init text message application ------------------------------------ */
switch (ReceiverParam.Service[iCurSelServ].AudioParam.bTextflag)
{
case TRUE:
bTextMessageUsed = TRUE;
/* Get a pointer to the string */
TextMessage.Init(&ReceiverParam.Service[iCurSelServ].AudioParam.
strTextMessage);
/* Total frame size is input block size minus the bytes for the text
message */
iTotalFrameSize = iInputBlockSize -
SIZEOF__BYTE * NUM_BYTES_TEXT_MESS_IN_AUD_STR;
/* Init vector for text message bytes */
vecbiTextMessBuf.Init(SIZEOF__BYTE * NUM_BYTES_TEXT_MESS_IN_AUD_STR);
break;
case FALSE:
bTextMessageUsed = FALSE;
/* All bytes are used for AAC data, no text message present */
iTotalFrameSize = iInputBlockSize;
break;
}
#ifdef USE_FAAD2_LIBRARY
/* Init for AAC decoding -------------------------------------------- */
/* Check, if AAC is used */
if (ReceiverParam.Service[iCurSelServ].AudioParam.
eAudioCoding != CParameter::AC_AAC)
{
throw CInitErr(ET_AAC);
}
/* Init "audio was ok" flag */
bAudioWasOK = TRUE;
/* Length of higher protected part of audio stream */
iLenAudHigh = ReceiverParam.Stream[iCurAudioStreamID].iLenPartA;
/* Set number of AAC frames in a AAC super-frame */
switch (ReceiverParam.Service[iCurSelServ].AudioParam.eAudioSamplRate)
{ /* only 12 kHz and 24 kHz is allowed */
case CParameter::AS_12KHZ:
iNumAACFrames = 5;
iNumHeaderBytes = 6;
iAACSampleRate = 12000;
break;
case CParameter::AS_24KHZ:
iNumAACFrames = 10;
iNumHeaderBytes = 14;
iAACSampleRate = 24000;
break;
default:
/* Some error occurred, throw error */
throw CInitErr(ET_AAC);
break;
}
/* Number of borders */
iNumBorders = iNumAACFrames - 1;
/* Set number of AAC frames for log file */
ReceiverParam.ReceptLog.SetNumAAC(iNumAACFrames);
/* Number of channels for AAC: Mono, PStereo, Stereo */
switch (ReceiverParam.Service[iCurSelServ].AudioParam.eAudioMode)
{
case CParameter::AM_MONO:
if (ReceiverParam.Service[iCurSelServ].AudioParam.
eSBRFlag == CParameter::SB_USED)
{
iDRMchanMode = DRMCH_SBR_MONO;
}
else
iDRMchanMode = DRMCH_MONO;
break;
case CParameter::AM_P_STEREO:
/* Low-complexity only defined in SBR mode */
iDRMchanMode = DRMCH_SBR_PS_STEREO;
break;
case CParameter::AM_STEREO:
if (ReceiverParam.Service[iCurSelServ].AudioParam.
eSBRFlag == CParameter::SB_USED)
{
iDRMchanMode = DRMCH_SBR_STEREO;
}
else
{
iDRMchanMode = DRMCH_STEREO;
}
break;
}
/* In case of SBR, AAC sample rate is half the total sample rate. Length
of output is doubled if SBR is used */
if (ReceiverParam.Service[iCurSelServ].AudioParam.
eSBRFlag == CParameter::SB_USED)
{
iAudioSampleRate = iAACSampleRate * 2;
iLenDecOutPerChan = AUD_DEC_TRANSFROM_LENGTH * 2;
}
else
{
iAudioSampleRate = iAACSampleRate;
iLenDecOutPerChan = AUD_DEC_TRANSFROM_LENGTH;
}
/* The audio_payload_length is derived from the length of the audio
super frame (data_length_of_part_A + data_length_of_part_B)
subtracting the audio super frame overhead (bytes used for the audio
super frame header() and for the aac_crc_bits) (5.3.1.1, Table 5) */
iAudioPayloadLen =
iTotalFrameSize / SIZEOF__BYTE - iNumHeaderBytes - iNumAACFrames;
/* Check iAudioPayloadLen value, only positive values make sense */
if (iAudioPayloadLen < 0)
throw CInitErr(ET_AAC);
/* Calculate number of bytes for higher protected blocks */
iNumHigherProtectedBytes =
(iLenAudHigh - iNumHeaderBytes - iNumAACFrames /* CRC bytes */) /
iNumAACFrames;
if (iNumHigherProtectedBytes < 0)
iNumHigherProtectedBytes = 0;
/* Since we do not correct for sample rate offsets here (yet), we do not
have to consider larger buffers. An audio frame always corresponds
to 400 ms */
iMaxLenResamplerOutput = (int) ((_REAL) SOUNDCRD_SAMPLE_RATE *
(_REAL) 0.4 /* 400ms */ * 2 /* for stereo */);
iResOutBlockSize = (int) ((_REAL) iLenDecOutPerChan *
SOUNDCRD_SAMPLE_RATE / iAudioSampleRate);
/* Additional buffers needed for resampling since we need conversation
between _REAL and _SAMPLE. We have to init the buffers with
zeros since it can happen, that we have bad CRC right at the
start of audio blocks */
vecTempResBufInLeft.Init(iLenDecOutPerChan);
vecTempResBufInRight.Init(iLenDecOutPerChan);
vecTempResBufOutCurLeft.Init(iResOutBlockSize, (_REAL) 0.0);
vecTempResBufOutCurRight.Init(iResOutBlockSize, (_REAL) 0.0);
vecTempResBufOutOldLeft.Init(iResOutBlockSize, (_REAL) 0.0);
vecTempResBufOutOldRight.Init(iResOutBlockSize, (_REAL) 0.0);
/* Init resample objects */
ResampleObjL.Init(iLenDecOutPerChan,
(_REAL) SOUNDCRD_SAMPLE_RATE / iAudioSampleRate);
ResampleObjR.Init(iLenDecOutPerChan,
(_REAL) SOUNDCRD_SAMPLE_RATE / iAudioSampleRate);
/* Clear reverberation object */
AudioRev.Clear();
/* AAC decoder ------------------------------------------------------ */
/* The maximum length for one audio frame is "iAudioPayloadLen". The
regular size will be much shorter since all audio frames share the
total size, but we do not know at this time how the data is
split in the transmitter source coder */
iMaxLenOneAudFrame = iAudioPayloadLen;
audio_frame.Init(iNumAACFrames, iMaxLenOneAudFrame);
/* Init vector which stores the data with the CRC at the beginning
("+ 1" for CRC) */
vecbyPrepAudioFrame.Init(iMaxLenOneAudFrame + 1);
/* Init storage for CRCs and frame lengths */
aac_crc_bits.Init(iNumAACFrames);
veciFrameLength.Init(iNumAACFrames);
/* Init AAC-decoder */
NeAACDecInitDRM(&HandleAACDecoder, iAACSampleRate, iDRMchanMode);
/* With this parameter we define the maximum lenght of the output
buffer. The cyclic buffer is only needed if we do a sample rate
correction due to a difference compared to the transmitter. But for
now we do not correct and we could stay with a single buffer
Maybe TODO: sample rate correction to avoid audio dropouts */
iMaxOutputBlockSize = iMaxLenResamplerOutput;
#else
/* No audio output if AAC library is not used */
iOutputBlockSize = 0;
#endif
}
catch (CInitErr CurErr)
{
switch (CurErr.eErrType)
{
case ET_ALL:
/* An init error occurred, do not process data in this module */
DoNotProcessData = TRUE;
break;
case ET_AAC:
/* AAC part should not be decdoded, set flag */
DoNotProcessAAC = TRUE;
break;
default:
DoNotProcessData = TRUE;
}
/* In all cases set output size to zero */
iOutputBlockSize = 0;
}
}
int CAudioSourceDecoder::GetNumCorDecAudio()
{
/* Return number of correctly decoded audio blocks. Reset counter
afterwards */
const int iRet = iNumCorDecAudio;
iNumCorDecAudio = 0;
return iRet;
}
CAudioSourceDecoder::CAudioSourceDecoder()
#ifdef USE_FAAD2_LIBRARY
: AudioRev((CReal) 1.0 /* seconds delay */), bUseReverbEffect(TRUE)
#endif
{
#ifdef USE_FAAD2_LIBRARY
/* Open AACEncoder instance */
HandleAACDecoder = NeAACDecOpen();
/* Decoder MUST be initialized at least once, therefore do it here in the
constructor with arbitrary values to be sure that this is satisfied */
NeAACDecInitDRM(&HandleAACDecoder, 24000, DRMCH_MONO);
#endif
}
CAudioSourceDecoder::~CAudioSourceDecoder()
{
#ifdef USE_FAAD2_LIBRARY
/* Close decoder handle */
NeAACDecClose(HandleAACDecoder);
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -