823 lines
27 KiB
C++
823 lines
27 KiB
C++
/* ------------------------------------------------------------------
|
|
* Copyright (C) 1998-2009 PacketVideo
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
|
* express or implied.
|
|
* See the License for the specific language governing permissions
|
|
* and limitations under the License.
|
|
* -------------------------------------------------------------------
|
|
*/
|
|
/*
|
|
------------------------------------------------------------------------------
|
|
|
|
PacketVideo Corp.
|
|
MP3 Decoder Library
|
|
|
|
Filename: pvmp3_framedecoder.cpp
|
|
|
|
Functions:
|
|
pvmp3_framedecoder
|
|
pvmp3_InitDecoder
|
|
pvmp3_resetDecoder
|
|
|
|
Date: 09/21/2007
|
|
|
|
------------------------------------------------------------------------------
|
|
REVISION HISTORY
|
|
|
|
|
|
Description:
|
|
|
|
------------------------------------------------------------------------------
|
|
INPUT AND OUTPUT DEFINITIONS
|
|
|
|
Input
|
|
pExt = pointer to the external interface structure. See the file
|
|
pvmp3decoder_api.h for a description of each field.
|
|
Data type of pointer to a tPVMP3DecoderExternal
|
|
structure.
|
|
|
|
pMem = void pointer to hide the internal implementation of the library
|
|
It is cast back to a tmp3dec_file structure. This structure
|
|
contains information that needs to persist between calls to
|
|
this function, or is too big to be placed on the stack, even
|
|
though the data is only needed during execution of this function
|
|
Data type void pointer, internally pointer to a tmp3dec_file
|
|
structure.
|
|
|
|
|
|
Outputs:
|
|
status = ERROR condition. see structure ERROR_CODE
|
|
|
|
Pointers and Buffers Modified:
|
|
pMem contents are modified.
|
|
pExt: (more detail in the file pvmp3decoder_api.h)
|
|
inputBufferUsedLength - number of array elements used up by the stream.
|
|
samplingRate - sampling rate in samples per sec
|
|
bitRate - bit rate in bits per second, varies frame to frame.
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
FUNCTIONS DESCRIPTION
|
|
|
|
pvmp3_framedecoder
|
|
frame decoder library driver
|
|
pvmp3_InitDecoder
|
|
Decoder Initialization
|
|
pvmp3_resetDecoder
|
|
Reset Decoder
|
|
|
|
------------------------------------------------------------------------------
|
|
REQUIREMENTS
|
|
|
|
|
|
------------------------------------------------------------------------------
|
|
REFERENCES
|
|
|
|
[1] ISO MPEG Audio Subgroup Software Simulation Group (1996)
|
|
ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension
|
|
|
|
------------------------------------------------------------------------------
|
|
PSEUDO-CODE
|
|
|
|
------------------------------------------------------------------------------
|
|
*/
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
; INCLUDES
|
|
----------------------------------------------------------------------------*/
|
|
|
|
|
|
#include "pvmp3_framedecoder.h"
|
|
#include "pvmp3_dec_defs.h"
|
|
#include "pvmp3_poly_phase_synthesis.h"
|
|
#include "pvmp3_tables.h"
|
|
#include "pvmp3_imdct_synth.h"
|
|
#include "pvmp3_alias_reduction.h"
|
|
#include "pvmp3_reorder.h"
|
|
#include "pvmp3_dequantize_sample.h"
|
|
#include "pvmp3_stereo_proc.h"
|
|
#include "pvmp3_mpeg2_stereo_proc.h"
|
|
#include "pvmp3_get_side_info.h"
|
|
#include "pvmp3_get_scale_factors.h"
|
|
#include "pvmp3_mpeg2_get_scale_factors.h"
|
|
#include "pvmp3_decode_header.h"
|
|
#include "pvmp3_get_main_data_size.h"
|
|
#include "s_tmp3dec_file.h"
|
|
#include "pvmp3_getbits.h"
|
|
#include "mp3_mem_funcs.h"
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
; MACROS
|
|
; Define module specific macros here
|
|
----------------------------------------------------------------------------*/
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
; DEFINES
|
|
; Include all pre-processor statements here. Include conditional
|
|
; compile variables also.
|
|
----------------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------------
|
|
; LOCAL FUNCTION DEFINITIONS
|
|
; Function Prototype declaration
|
|
----------------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------------
|
|
; LOCAL STORE/BUFFER/POINTER DEFINITIONS
|
|
; Variable declaration - defined here and used outside this module
|
|
----------------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------------
|
|
; EXTERNAL FUNCTION REFERENCES
|
|
; Declare functions defined elsewhere and referenced in this module
|
|
----------------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------------
|
|
; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
|
|
; Declare variables used in this module but defined elsewhere
|
|
----------------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------------
|
|
; FUNCTION CODE
|
|
----------------------------------------------------------------------------*/
|
|
|
|
ERROR_CODE pvmp3_framedecoder(tPVMP3DecoderExternal *pExt,
|
|
void *pMem)
|
|
{
|
|
|
|
ERROR_CODE errorCode = NO_DECODING_ERROR;
|
|
|
|
int32 crc_error_count = 0;
|
|
uint32 sent_crc = 0;
|
|
uint32 computed_crc = 0;
|
|
|
|
tmp3dec_chan *pChVars[CHAN];
|
|
tmp3dec_file *pVars = (tmp3dec_file *)pMem;
|
|
|
|
mp3Header info_data;
|
|
mp3Header *info = &info_data;
|
|
|
|
pVars->inputStream.pBuffer = pExt->pInputBuffer;
|
|
|
|
|
|
pVars->inputStream.usedBits = pExt->inputBufferUsedLength << 3;
|
|
pVars->inputStream.inputBufferCurrentLength = pExt->inputBufferCurrentLength;
|
|
|
|
|
|
errorCode = pvmp3_decode_header(&pVars->inputStream,
|
|
info,
|
|
&computed_crc);
|
|
|
|
if (errorCode != NO_DECODING_ERROR)
|
|
{
|
|
pExt->outputFrameSize = 0;
|
|
return errorCode;
|
|
}
|
|
|
|
pVars->num_channels = (info->mode == MPG_MD_MONO) ? 1 : 2;
|
|
pExt->num_channels = pVars->num_channels;
|
|
|
|
int32 outputFrameSize = (info->version_x == MPEG_1) ?
|
|
2 * SUBBANDS_NUMBER * FILTERBANK_BANDS :
|
|
SUBBANDS_NUMBER * FILTERBANK_BANDS;
|
|
|
|
outputFrameSize = (info->mode == MPG_MD_MONO) ? outputFrameSize : outputFrameSize << 1;
|
|
|
|
|
|
/*
|
|
* Check if output buffer has enough room to hold output PCM
|
|
*/
|
|
if (pExt->outputFrameSize >= outputFrameSize)
|
|
{
|
|
pExt->outputFrameSize = outputFrameSize;
|
|
}
|
|
else
|
|
{
|
|
pExt->outputFrameSize = 0;
|
|
return OUTPUT_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
|
|
pChVars[ LEFT] = &pVars->perChan[ LEFT];
|
|
pChVars[RIGHT] = &pVars->perChan[RIGHT];
|
|
|
|
|
|
|
|
|
|
if (info->error_protection)
|
|
{
|
|
if (!bitsAvailable(&pVars->inputStream, 16))
|
|
{
|
|
return SIDE_INFO_ERROR;
|
|
}
|
|
|
|
/*
|
|
* Get crc content
|
|
*/
|
|
sent_crc = getUpTo17bits(&pVars->inputStream, 16);
|
|
}
|
|
|
|
|
|
if (info->layer_description == 3)
|
|
{
|
|
int32 gr;
|
|
int32 ch;
|
|
uint32 main_data_end;
|
|
int32 bytes_to_discard;
|
|
int16 *ptrOutBuffer = pExt->pOutputBuffer;
|
|
|
|
/*
|
|
* Side Information must be extracted from the bitstream and store for use
|
|
* during the decoded of the associated frame
|
|
*/
|
|
|
|
errorCode = pvmp3_get_side_info(&pVars->inputStream,
|
|
&pVars->sideInfo,
|
|
info,
|
|
&computed_crc);
|
|
|
|
if (errorCode != NO_DECODING_ERROR)
|
|
{
|
|
pExt->outputFrameSize = 0;
|
|
return errorCode;
|
|
}
|
|
|
|
/*
|
|
* If CRC was sent, check that matches the one got while parsing data
|
|
* disable crc if this is the desired mode
|
|
*/
|
|
if (info->error_protection)
|
|
{
|
|
if ((computed_crc != sent_crc) && pExt->crcEnabled)
|
|
{
|
|
crc_error_count++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* main data (scalefactors, Huffman coded, etc,) are not necessarily located
|
|
* adjacent to the side-info. Beginning of main data is located using
|
|
* field "main_data_begin" of the current frame. The length does not include
|
|
* header and side info.
|
|
* "main_data_begin" points to the first bit of main data of a frame. It is a negative
|
|
* offset in bytes from the first byte of the sync word
|
|
* main_data_begin = 0 <===> main data start rigth after side info.
|
|
*/
|
|
|
|
int32 temp = pvmp3_get_main_data_size(info, pVars);
|
|
|
|
|
|
/*
|
|
* Check if available data holds a full frame, if not flag an error
|
|
*/
|
|
|
|
if ((uint32)pVars->predicted_frame_size > pVars->inputStream.inputBufferCurrentLength)
|
|
{
|
|
pExt->outputFrameSize = 0;
|
|
return NO_ENOUGH_MAIN_DATA_ERROR;
|
|
}
|
|
|
|
/*
|
|
* Fill in internal circular buffer
|
|
*/
|
|
fillMainDataBuf(pVars, temp);
|
|
|
|
|
|
main_data_end = pVars->mainDataStream.usedBits >> 3; /* in bytes */
|
|
if ((main_data_end << 3) < pVars->mainDataStream.usedBits)
|
|
{
|
|
main_data_end++;
|
|
pVars->mainDataStream.usedBits = main_data_end << 3;
|
|
}
|
|
|
|
|
|
// force signed computation; buffer sizes and offsets are all going to be
|
|
// well within the constraints of 32-bit signed math.
|
|
bytes_to_discard = pVars->frame_start
|
|
- ((int32)pVars->sideInfo.main_data_begin)
|
|
- ((int32)main_data_end);
|
|
|
|
|
|
if (main_data_end > BUFSIZE) /* check overflow on the buffer */
|
|
{
|
|
pVars->frame_start -= BUFSIZE;
|
|
|
|
pVars->mainDataStream.usedBits -= (BUFSIZE << 3);
|
|
}
|
|
|
|
pVars->frame_start += temp;
|
|
|
|
|
|
if (bytes_to_discard < 0 || crc_error_count)
|
|
{
|
|
/*
|
|
* Not enough data to decode, then we should avoid reading this
|
|
* data ( getting/ignoring sido info and scale data)
|
|
* Main data could be located in the previous frame, so an unaccounted
|
|
* frame can cause incorrect processing
|
|
* Just run the polyphase filter to "clean" the history buffer
|
|
*/
|
|
errorCode = NO_ENOUGH_MAIN_DATA_ERROR;
|
|
|
|
/*
|
|
* Clear the input to these filters
|
|
*/
|
|
|
|
pv_memset((void*)pChVars[RIGHT]->work_buf_int32,
|
|
0,
|
|
SUBBANDS_NUMBER*FILTERBANK_BANDS*sizeof(pChVars[RIGHT]->work_buf_int32[0]));
|
|
|
|
pv_memset((void*)pChVars[LEFT]->work_buf_int32,
|
|
0,
|
|
SUBBANDS_NUMBER*FILTERBANK_BANDS*sizeof(pChVars[LEFT]->work_buf_int32[0]));
|
|
|
|
/* clear circular buffers, to avoid any glitch */
|
|
pv_memset((void*)&pChVars[ LEFT]->circ_buffer[576],
|
|
0,
|
|
480*sizeof(pChVars[ LEFT]->circ_buffer[0]));
|
|
pv_memset((void*)&pChVars[RIGHT]->circ_buffer[576],
|
|
0,
|
|
480*sizeof(pChVars[RIGHT]->circ_buffer[0]));
|
|
|
|
pChVars[ LEFT]->used_freq_lines = 575;
|
|
pChVars[RIGHT]->used_freq_lines = 575;
|
|
|
|
}
|
|
else
|
|
{
|
|
pVars->mainDataStream.usedBits += (bytes_to_discard << 3);
|
|
}
|
|
|
|
/*
|
|
* if (fr_ps->header->version_x == MPEG_1), use 2 granules, otherwise just 1
|
|
*/
|
|
for (gr = 0; gr < (1 + !(info->version_x)); gr++)
|
|
{
|
|
if (errorCode != NO_ENOUGH_MAIN_DATA_ERROR)
|
|
{
|
|
for (ch = 0; ch < pVars->num_channels; ch++)
|
|
{
|
|
int32 part2_start = pVars->mainDataStream.usedBits;
|
|
|
|
if (info->version_x == MPEG_1)
|
|
{
|
|
|
|
pvmp3_get_scale_factors(&pVars->scaleFactors[ch],
|
|
&pVars->sideInfo,
|
|
gr,
|
|
ch,
|
|
&pVars->mainDataStream);
|
|
}
|
|
else
|
|
{
|
|
int32 * tmp = pVars->Scratch_mem;
|
|
pvmp3_mpeg2_get_scale_factors(&pVars->scaleFactors[ch],
|
|
&pVars->sideInfo,
|
|
gr,
|
|
ch,
|
|
info,
|
|
(uint32 *)tmp,
|
|
&pVars->mainDataStream);
|
|
}
|
|
|
|
pChVars[ch]->used_freq_lines = pvmp3_huffman_parsing(pChVars[ch]->work_buf_int32,
|
|
&pVars->sideInfo.ch[ch].gran[gr],
|
|
pVars,
|
|
part2_start,
|
|
info);
|
|
|
|
|
|
pvmp3_dequantize_sample(pChVars[ch]->work_buf_int32,
|
|
&pVars->scaleFactors[ch],
|
|
&pVars->sideInfo.ch[ch].gran[gr],
|
|
pChVars[ch]->used_freq_lines,
|
|
info);
|
|
|
|
|
|
|
|
|
|
} /* for (ch=0; ch<stereo; ch++) */
|
|
|
|
if (pVars->num_channels == 2)
|
|
{
|
|
|
|
int32 used_freq_lines = (pChVars[ LEFT]->used_freq_lines >
|
|
pChVars[RIGHT]->used_freq_lines) ?
|
|
pChVars[ LEFT]->used_freq_lines :
|
|
pChVars[RIGHT]->used_freq_lines;
|
|
|
|
pChVars[ LEFT]->used_freq_lines = used_freq_lines;
|
|
pChVars[RIGHT]->used_freq_lines = used_freq_lines;
|
|
|
|
if (info->version_x == MPEG_1)
|
|
{
|
|
pvmp3_stereo_proc(pChVars[ LEFT]->work_buf_int32,
|
|
pChVars[RIGHT]->work_buf_int32,
|
|
&pVars->scaleFactors[RIGHT],
|
|
&pVars->sideInfo.ch[LEFT].gran[gr],
|
|
used_freq_lines,
|
|
info);
|
|
}
|
|
else
|
|
{
|
|
int32 * tmp = pVars->Scratch_mem;
|
|
pvmp3_mpeg2_stereo_proc(pChVars[ LEFT]->work_buf_int32,
|
|
pChVars[RIGHT]->work_buf_int32,
|
|
&pVars->scaleFactors[RIGHT],
|
|
&pVars->sideInfo.ch[ LEFT].gran[gr],
|
|
&pVars->sideInfo.ch[RIGHT].gran[gr],
|
|
(uint32 *)tmp,
|
|
used_freq_lines,
|
|
info);
|
|
}
|
|
}
|
|
|
|
} /* if ( errorCode != NO_ENOUGH_MAIN_DATA_ERROR) */
|
|
|
|
for (ch = 0; ch < pVars->num_channels; ch++)
|
|
{
|
|
|
|
pvmp3_reorder(pChVars[ch]->work_buf_int32,
|
|
&pVars->sideInfo.ch[ch].gran[gr],
|
|
&pChVars[ ch]->used_freq_lines,
|
|
info,
|
|
pVars->Scratch_mem);
|
|
|
|
pvmp3_alias_reduction(pChVars[ch]->work_buf_int32,
|
|
&pVars->sideInfo.ch[ch].gran[gr],
|
|
&pChVars[ ch]->used_freq_lines,
|
|
info);
|
|
|
|
|
|
/*
|
|
* IMDCT
|
|
*/
|
|
/* set mxposition
|
|
* In case of mixed blocks, # of bands with long
|
|
* blocks (2 or 4) else 0
|
|
*/
|
|
uint16 mixedBlocksLongBlocks = 0; /* 0 = long or short, 2=mixed, 4=mixed 2.5@8000 */
|
|
if (pVars->sideInfo.ch[ch].gran[gr].mixed_block_flag &&
|
|
pVars->sideInfo.ch[ch].gran[gr].window_switching_flag)
|
|
{
|
|
if ((info->version_x == MPEG_2_5) && (info->sampling_frequency == 2))
|
|
{
|
|
mixedBlocksLongBlocks = 4; /* mpeg2.5 @ 8 KHz */
|
|
}
|
|
else
|
|
{
|
|
mixedBlocksLongBlocks = 2;
|
|
}
|
|
}
|
|
|
|
pvmp3_imdct_synth(pChVars[ch]->work_buf_int32,
|
|
pChVars[ch]->overlap,
|
|
pVars->sideInfo.ch[ch].gran[gr].block_type,
|
|
mixedBlocksLongBlocks,
|
|
pChVars[ ch]->used_freq_lines,
|
|
pVars->Scratch_mem);
|
|
|
|
|
|
/*
|
|
* Polyphase synthesis
|
|
*/
|
|
|
|
pvmp3_poly_phase_synthesis(pChVars[ch],
|
|
pVars->num_channels,
|
|
pExt->equalizerType,
|
|
&ptrOutBuffer[ch]);
|
|
|
|
|
|
}/* end ch loop */
|
|
|
|
ptrOutBuffer += pVars->num_channels * SUBBANDS_NUMBER * FILTERBANK_BANDS;
|
|
} /* for (gr=0;gr<Max_gr;gr++) */
|
|
|
|
/* skip ancillary data */
|
|
if (info->bitrate_index > 0)
|
|
{ /* if not free-format */
|
|
|
|
int32 ancillary_data_lenght = pVars->predicted_frame_size << 3;
|
|
|
|
ancillary_data_lenght -= pVars->inputStream.usedBits;
|
|
|
|
/* skip ancillary data */
|
|
if (ancillary_data_lenght > 0)
|
|
{
|
|
pVars->inputStream.usedBits += ancillary_data_lenght;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* This overrides a possible NO_ENOUGH_MAIN_DATA_ERROR
|
|
*/
|
|
errorCode = NO_DECODING_ERROR;
|
|
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The info on the header leads to an unsupported layer, more data
|
|
* will not fix this, so this is a bad frame,
|
|
*/
|
|
|
|
pExt->outputFrameSize = 0;
|
|
return UNSUPPORTED_LAYER;
|
|
}
|
|
|
|
pExt->inputBufferUsedLength = pVars->inputStream.usedBits >> 3;
|
|
pExt->totalNumberOfBitsUsed += pVars->inputStream.usedBits;
|
|
pExt->version = info->version_x;
|
|
pExt->samplingRate = mp3_s_freq[info->version_x][info->sampling_frequency];
|
|
pExt->bitRate = mp3_bitrate[pExt->version][info->bitrate_index];
|
|
|
|
|
|
/*
|
|
* Always verify buffer overrun condition
|
|
*/
|
|
|
|
if (pExt->inputBufferUsedLength > pExt->inputBufferCurrentLength)
|
|
{
|
|
pExt->outputFrameSize = 0;
|
|
errorCode = NO_ENOUGH_MAIN_DATA_ERROR;
|
|
}
|
|
|
|
return errorCode;
|
|
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
; FUNCTION CODE
|
|
----------------------------------------------------------------------------*/
|
|
|
|
__inline void fillDataBuf(tmp3Bits *pMainData,
|
|
uint32 val) /* val to write into the buffer */
|
|
{
|
|
pMainData->pBuffer[module(pMainData->offset++, BUFSIZE)] = (uint8)val;
|
|
}
|
|
|
|
|
|
void fillMainDataBuf(void *pMem, int32 temp)
|
|
{
|
|
tmp3dec_file *pVars = (tmp3dec_file *)pMem;
|
|
|
|
|
|
int32 offset = (pVars->inputStream.usedBits) >> INBUF_ARRAY_INDEX_SHIFT;
|
|
|
|
/*
|
|
* Check if input circular buffer boundaries need to be enforced
|
|
*/
|
|
if ((offset + temp) < BUFSIZE)
|
|
{
|
|
uint8 * ptr = pVars->inputStream.pBuffer + offset;
|
|
|
|
offset = pVars->mainDataStream.offset;
|
|
|
|
/*
|
|
* Check if main data circular buffer boundaries need to be enforced
|
|
*/
|
|
if ((offset + temp) < BUFSIZE)
|
|
{
|
|
pv_memcpy((pVars->mainDataStream.pBuffer + offset), ptr, temp*sizeof(uint8));
|
|
pVars->mainDataStream.offset += temp;
|
|
}
|
|
else
|
|
{
|
|
for (int32 nBytes = temp; nBytes != 0; nBytes--) /* read main data. */
|
|
{
|
|
int32 tmp = *(ptr++);
|
|
fillDataBuf(&pVars->mainDataStream, tmp);
|
|
}
|
|
|
|
/* adjust circular buffer counter */
|
|
pVars->mainDataStream.offset = module(pVars->mainDataStream.offset, BUFSIZE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int32 nBytes = temp; nBytes != 0; nBytes--) /* read main data. */
|
|
{
|
|
fillDataBuf(&pVars->mainDataStream, *(pVars->inputStream.pBuffer + module(offset++ , BUFSIZE)));
|
|
}
|
|
}
|
|
|
|
|
|
pVars->inputStream.usedBits += (temp) << INBUF_ARRAY_INDEX_SHIFT;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
; FUNCTION CODE
|
|
----------------------------------------------------------------------------*/
|
|
|
|
uint32 pvmp3_decoderMemRequirements(void)
|
|
{
|
|
uint32 size;
|
|
|
|
size = (uint32) sizeof(tmp3dec_file);
|
|
return (size);
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
; FUNCTION CODE
|
|
----------------------------------------------------------------------------*/
|
|
|
|
#include "pvmp3_decode_huff_cw.h"
|
|
|
|
void pvmp3_InitDecoder(tPVMP3DecoderExternal *pExt,
|
|
void *pMem)
|
|
{
|
|
|
|
tmp3dec_file *pVars;
|
|
huffcodetab *pHuff;
|
|
|
|
pVars = (tmp3dec_file *)pMem;
|
|
memset(pVars, 0, sizeof(*pVars));
|
|
|
|
pExt->totalNumberOfBitsUsed = 0;
|
|
pExt->inputBufferCurrentLength = 0;
|
|
pExt->inputBufferUsedLength = 0;
|
|
|
|
pVars->inputStream.pBuffer = pExt->pInputBuffer;
|
|
|
|
/*
|
|
* Initialize huffman decoding table
|
|
*/
|
|
|
|
pHuff = pVars->ht;
|
|
pHuff[0].linbits = 0;
|
|
pHuff[0].pdec_huff_tab = pvmp3_decode_huff_cw_tab0;
|
|
pHuff[1].linbits = 0;
|
|
pHuff[1].pdec_huff_tab = pvmp3_decode_huff_cw_tab1;
|
|
pHuff[2].linbits = 0;
|
|
pHuff[2].pdec_huff_tab = pvmp3_decode_huff_cw_tab2;
|
|
pHuff[3].linbits = 0;
|
|
pHuff[3].pdec_huff_tab = pvmp3_decode_huff_cw_tab3;
|
|
pHuff[4].linbits = 0;
|
|
pHuff[4].pdec_huff_tab = pvmp3_decode_huff_cw_tab0; /* tbl 4 is not used */
|
|
pHuff[5].linbits = 4;
|
|
pHuff[5].pdec_huff_tab = pvmp3_decode_huff_cw_tab5;
|
|
pHuff[6].linbits = 0;
|
|
pHuff[6].pdec_huff_tab = pvmp3_decode_huff_cw_tab6;
|
|
pHuff[7].linbits = 0;
|
|
pHuff[7].pdec_huff_tab = pvmp3_decode_huff_cw_tab7;
|
|
pHuff[8].linbits = 0;
|
|
pHuff[8].pdec_huff_tab = pvmp3_decode_huff_cw_tab8;
|
|
pHuff[9].linbits = 0;
|
|
pHuff[9].pdec_huff_tab = pvmp3_decode_huff_cw_tab9;
|
|
pHuff[10].linbits = 0;
|
|
pHuff[10].pdec_huff_tab = pvmp3_decode_huff_cw_tab10;
|
|
pHuff[11].linbits = 0;
|
|
pHuff[11].pdec_huff_tab = pvmp3_decode_huff_cw_tab11;
|
|
pHuff[12].linbits = 0;
|
|
pHuff[12].pdec_huff_tab = pvmp3_decode_huff_cw_tab12;
|
|
pHuff[13].linbits = 0;
|
|
pHuff[13].pdec_huff_tab = pvmp3_decode_huff_cw_tab13;
|
|
pHuff[14].linbits = 0;
|
|
pHuff[14].pdec_huff_tab = pvmp3_decode_huff_cw_tab0; /* tbl 14 is not used */
|
|
pHuff[15].linbits = 0;
|
|
pHuff[15].pdec_huff_tab = pvmp3_decode_huff_cw_tab15;
|
|
pHuff[16].linbits = 1;
|
|
pHuff[16].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
|
|
pHuff[17].linbits = 2;
|
|
pHuff[17].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
|
|
pHuff[18].linbits = 3;
|
|
pHuff[18].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
|
|
pHuff[19].linbits = 4;
|
|
pHuff[19].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
|
|
pHuff[20].linbits = 6;
|
|
pHuff[20].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
|
|
pHuff[21].linbits = 8;
|
|
pHuff[21].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
|
|
pHuff[22].linbits = 10;
|
|
pHuff[22].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
|
|
pHuff[23].linbits = 13;
|
|
pHuff[23].pdec_huff_tab = pvmp3_decode_huff_cw_tab16;
|
|
pHuff[24].linbits = 4;
|
|
pHuff[24].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
|
|
pHuff[25].linbits = 5;
|
|
pHuff[25].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
|
|
pHuff[26].linbits = 6;
|
|
pHuff[26].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
|
|
pHuff[27].linbits = 7;
|
|
pHuff[27].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
|
|
pHuff[28].linbits = 8;
|
|
pHuff[28].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
|
|
pHuff[29].linbits = 9;
|
|
pHuff[29].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
|
|
pHuff[30].linbits = 11;
|
|
pHuff[30].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
|
|
pHuff[31].linbits = 13;
|
|
pHuff[31].pdec_huff_tab = pvmp3_decode_huff_cw_tab24;
|
|
pHuff[32].linbits = 0;
|
|
pHuff[32].pdec_huff_tab = pvmp3_decode_huff_cw_tab32;
|
|
pHuff[33].linbits = 0;
|
|
pHuff[33].pdec_huff_tab = pvmp3_decode_huff_cw_tab33;
|
|
|
|
/*
|
|
* Initialize polysynthesis circular buffer mechanism
|
|
*/
|
|
/* clear buffers */
|
|
|
|
pvmp3_resetDecoder(pMem);
|
|
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
; FUNCTION CODE
|
|
----------------------------------------------------------------------------*/
|
|
|
|
|
|
void pvmp3_resetDecoder(void *pMem)
|
|
{
|
|
|
|
tmp3dec_file *pVars;
|
|
tmp3dec_chan *pChVars[CHAN];
|
|
|
|
pVars = (tmp3dec_file *)pMem;
|
|
pChVars[ LEFT] = &pVars->perChan[ LEFT];
|
|
pChVars[RIGHT] = &pVars->perChan[RIGHT];
|
|
|
|
pVars->frame_start = 0;
|
|
|
|
pVars->mainDataStream.offset = 0;
|
|
|
|
pVars->mainDataStream.pBuffer = pVars->mainDataBuffer;
|
|
pVars->mainDataStream.usedBits = 0;
|
|
|
|
|
|
pVars->inputStream.usedBits = 0; // in bits
|
|
|
|
|
|
pChVars[ LEFT]->used_freq_lines = 575;
|
|
pChVars[RIGHT]->used_freq_lines = 575;
|
|
|
|
|
|
/*
|
|
* Initialize polysynthesis circular buffer mechanism
|
|
*/
|
|
|
|
pv_memset((void*)&pChVars[ LEFT]->circ_buffer[576],
|
|
0,
|
|
480*sizeof(pChVars[ LEFT]->circ_buffer[0]));
|
|
pv_memset((void*)&pChVars[RIGHT]->circ_buffer[576],
|
|
0,
|
|
480*sizeof(pChVars[RIGHT]->circ_buffer[0]));
|
|
|
|
|
|
pv_memset((void*)pChVars[ LEFT]->overlap,
|
|
0,
|
|
SUBBANDS_NUMBER*FILTERBANK_BANDS*sizeof(pChVars[ LEFT]->overlap[0]));
|
|
|
|
|
|
pv_memset((void*)pChVars[ RIGHT]->overlap,
|
|
0,
|
|
SUBBANDS_NUMBER*FILTERBANK_BANDS*sizeof(pChVars[ RIGHT]->overlap[0]));
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Clear all the structures
|
|
*/
|
|
|
|
|
|
pv_memset((void*)&pVars->scaleFactors[RIGHT],
|
|
0,
|
|
sizeof(mp3ScaleFactors));
|
|
|
|
pv_memset((void*)&pVars->scaleFactors[LEFT],
|
|
0,
|
|
sizeof(mp3ScaleFactors));
|
|
|
|
pv_memset((void*)&pVars->sideInfo,
|
|
0,
|
|
sizeof(mp3SideInfo));
|
|
|
|
pv_memset((void*)&pVars->sideInfo,
|
|
0,
|
|
sizeof(mp3SideInfo));
|
|
|
|
}
|