raze-gles/polymer/jfaud/mpadec/mpadec.c
terminx 197cf82051 Compile
git-svn-id: https://svn.eduke32.com/eduke32@453 1a8010ca-5511-0410-912e-c29ae57300e0
2007-01-12 23:24:13 +00:00

793 lines
32 KiB
C
Executable file

/*
* mpadec - MPEG audio decoder
* Copyright (C) 2002-2004 Dmitriy Startsev (dstartsev@rambler.ru)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* $Id: mpadec.c,v 1.2 2004/07/28 06:46:49 metal_man Exp $ */
#include "mpadec_internal.h"
extern const uint16_t crc_table[256];
extern void *synth_table[2][2][4][4];
const uint32_t bitmask[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F,
0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
const int32_t frequency_table[9] = { 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000 };
const int16_t bitrate_table[2][3][16] = {
{ { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 560 },
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448 },
{ 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 } },
{ { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 320 },
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 192 },
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 192 } }
};
extern void init_tables(mpadec_t mpadec, FLOAT scale, int32_t sblimit);
extern void decode_layer1(mpadec_t mpadec, uint8_t *buffer);
extern void decode_layer2(mpadec_t mpadec, uint8_t *buffer);
extern void decode_layer3(mpadec_t mpadec, uint8_t *buffer);
uint32_t getbits(mpadec_t mpadec, unsigned n)
{
register struct mpadec_t *mpa = (struct mpadec_t *)mpadec;
while ((mpa->bits_left <= 24) && mpa->bytes_left) {
mpa->bit_buffer = (mpa->bit_buffer << 8) | *mpa->next_byte++;
mpa->bits_left += (uint8_t)8;
mpa->bytes_left--;
}
while (mpa->bits_left <= 24) {
mpa->bit_buffer = (mpa->bit_buffer << 8);
mpa->bits_left += (uint8_t)8;
}
mpa->bits_left -= (uint8_t)n;
return (mpa->bit_buffer >> mpa->bits_left) & bitmask[n];
}
uint16_t update_crc(uint16_t init, uint8_t *buf, int length)
{
register uint32_t crc = (uint32_t)init, tmp;
register int l = length;
register uint8_t *b = buf;
for (; l >= 8; l -= 8) crc = (crc << 8) ^ crc_table[((crc >> 8) ^ (*b++)) & 0xFF];
tmp = (uint32_t)(*b) << 8;
while (l--) {
tmp <<= 1;
crc <<= 1;
if ((crc ^ tmp) & 0x10000) crc ^= 0x8005;
}
return (uint16_t)crc;
}
static uint32_t detect_frame_size(mpadec_t mpadec)
{
register struct mpadec_t *mpa = (struct mpadec_t *)mpadec;
register uint8_t *buf = mpa->next_byte;
uint32_t i = mpa->bytes_left, hdr = 0;
if (i < (mpa->frame.frame_size + 4)) return 0;
buf += mpa->frame.frame_size;
i -= mpa->frame.frame_size;
while (i >= 4) {
register uint32_t tmp = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
if (((tmp & 0xFFE00000) == 0xFFE00000) && (tmp & (3 << 17)) && ((tmp & (3 << 10)) != (3 << 10))) {
if ((mpa->frame.layer == (uint8_t)(4 - ((tmp >> 17) & 3))) &&
(mpa->frame.frequency_index == (((tmp >> 10) & 3) + 3*(mpa->frame.LSF + mpa->frame.MPEG25))) &&
(mpa->frame.channels == ((((tmp >> 6) & 3) == MPG_MD_MONO) ? 1 : 2))) {
if (mpa->config.dblsync) {
uint32_t fs = mpa->bytes_left - i - mpa->frame.padding + ((tmp >> 9) & 1);
if (i >= (fs + 4)) {
buf += fs;
tmp = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
buf -= fs;
if (((tmp & 0xFFE00000) == 0xFFE00000) && (tmp & (3 << 17)) && ((tmp & (3 << 10)) != (3 << 10))) {
if ((mpa->frame.layer == (uint8_t)(4 - ((tmp >> 17) & 3))) &&
(mpa->frame.frequency_index == (((tmp >> 10) & 3) + 3*(mpa->frame.LSF + mpa->frame.MPEG25))) &&
(mpa->frame.channels == ((((tmp >> 6) & 3) == MPG_MD_MONO) ? 1 : 2))) {
hdr = tmp;
break;
}
}
} else return 0;
} else {
hdr = tmp;
break;
}
}
}
buf++; i--;
}
return (hdr ? (mpa->bytes_left - i) : 0);
}
static int decode_header(mpadec_t mpadec, uint32_t header)
{
register struct mpadec_t *mpa = (struct mpadec_t *)mpadec;
unsigned int layer, bridx, fridx;
layer = 4 - ((header >> 17) & 3);
bridx = ((header >> 12) & 0x0F);
fridx = ((header >> 10) & 3);
if ((fridx == 3) || (layer == 4) || ((layer != 3) && !bridx)) return FALSE;
if (header & (1 << 20)) {
mpa->frame.LSF = (uint8_t)((header & (1 << 19)) ? FALSE : TRUE);
mpa->frame.MPEG25 = FALSE;
} else mpa->frame.LSF = mpa->frame.MPEG25 = TRUE;
mpa->frame.layer = (uint8_t)layer;
mpa->frame.bitrate_index = bridx;
mpa->frame.bitrate = bitrate_table[mpa->frame.LSF][layer - 1][bridx];
mpa->frame.frequency_index = (fridx += 3*(mpa->frame.LSF + mpa->frame.MPEG25));
mpa->frame.frequency = frequency_table[fridx];
mpa->frame.decoded_frequency = mpa->frame.frequency >> mpa->config.quality;
mpa->frame.CRC = (uint8_t)(((header >> 16) & 1) ^ 1);
mpa->frame.padding = ((header >> 9) & 1);
mpa->frame.extension = (uint8_t)((header >> 8) & 1);
mpa->frame.mode = (uint8_t)((header >> 6) & 3);
mpa->frame.mode_ext = (uint8_t)((header >> 4) & 3);
mpa->frame.copyright = (uint8_t)((header >> 3) & 1);
mpa->frame.original = (uint8_t)((header >> 2) & 1);
mpa->frame.emphasis = (uint8_t)(header & 3);
mpa->frame.channels = (uint8_t)((mpa->frame.mode == MPG_MD_MONO) ? 1 : 2);
switch (mpa->config.mode) {
case MPADEC_CONFIG_CHANNEL1:
case MPADEC_CONFIG_CHANNEL2:
case MPADEC_CONFIG_MONO: mpa->frame.decoded_channels = 1; break;
case MPADEC_CONFIG_STEREO: mpa->frame.decoded_channels = 2; break;
default: mpa->frame.decoded_channels = mpa->frame.channels;
}
mpa->free_format = FALSE;
switch (mpa->frame.layer) {
case 1: mpa->frame.frame_samples = 384;
mpa->frame.frame_size = (12000*mpa->frame.bitrate/mpa->frame.frequency + mpa->frame.padding) << 2;
mpa->ssize = 0;
break;
case 2: mpa->frame.frame_samples = 1152;
mpa->frame.frame_size = 144000*mpa->frame.bitrate/mpa->frame.frequency + mpa->frame.padding;
mpa->ssize = 0;
break;
case 3: mpa->frame.frame_samples = 1152 >> mpa->frame.LSF;
if (mpa->frame.LSF) mpa->ssize = (mpa->frame.channels > 1) ? 17 : 9;
else mpa->ssize = (mpa->frame.channels > 1) ? 32 : 17;
if (mpa->frame.bitrate_index) {
mpa->frame.frame_size = 144000*mpa->frame.bitrate/(mpa->frame.frequency << mpa->frame.LSF) + mpa->frame.padding;
mpa->prev_frame_size = 0;
} else {
register uint32_t div = 125*mpa->frame.frame_samples;
if (!mpa->prev_frame_size) {
mpa->frame.frame_size = (mpa->frame.CRC ? 6 : 4) + mpa->ssize + mpa->frame.padding;
mpa->prev_frame_size = detect_frame_size(mpa);
if (mpa->prev_frame_size) mpa->prev_frame_size -= mpa->frame.padding;
}
mpa->frame.frame_size = mpa->prev_frame_size + mpa->frame.padding;
mpa->frame.bitrate = (mpa->frame.frame_size*mpa->frame.frequency + (div >> 1))/div;
mpa->free_format = TRUE;
}
break;
}
mpa->frame.decoded_samples = mpa->frame.frame_samples >> mpa->config.quality;
mpa->frame.downsample = FALSE;
mpa->frame.downsample_sblimit = SBLIMIT;
mpa->frame.decoded_size = mpa->frame.decoded_samples*mpa->frame.decoded_channels;
switch (mpa->config.format) {
case MPADEC_CONFIG_24BIT: mpa->frame.decoded_size *= 3; break;
case MPADEC_CONFIG_32BIT:
case MPADEC_CONFIG_FLOAT: mpa->frame.decoded_size <<= 2; break;
default: mpa->frame.decoded_size <<= 1; break;
}
mpa->hsize = mpa->frame.CRC ? 6 : 4;
if (mpa->frame.frame_size < (mpa->hsize + mpa->ssize)) mpa->frame.frame_size = mpa->hsize + mpa->ssize;
mpa->dsize = mpa->frame.frame_size - (mpa->hsize + mpa->ssize);
return TRUE;
}
static uint32_t sync_buffer(mpadec_t mpadec)
{
register struct mpadec_t *mpa = (struct mpadec_t *)mpadec;
register uint8_t *buf = mpa->next_byte;
uint32_t retval = 0, i = mpa->bytes_left;
if (mpa->state == MPADEC_STATE_START) {
while (i >= 4) {
register uint32_t tmp = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
if (((tmp & 0xFFE00000) == 0xFFE00000) && (tmp & (3 << 17)) && ((tmp & (3 << 10)) != (3 << 10))) {
if (mpa->config.dblsync) {
if (decode_header(mpa, tmp)) {
if ((i < (mpa->frame.frame_size + 4)) || (mpa->free_format && !mpa->prev_frame_size)) break;
else {
register uint32_t tmp2 = (buf[mpa->frame.frame_size] << 24) | (buf[mpa->frame.frame_size + 1] << 16) | (buf[mpa->frame.frame_size + 2] << 8) | buf[mpa->frame.frame_size + 3];
if (((tmp2 & 0xFFE00000) == 0xFFE00000) && (tmp2 & (3 << 17)) && ((tmp2 & (3 << 10)) != (3 << 10))) {
if ((mpa->frame.layer == (uint8_t)(4 - ((tmp2 >> 17) & 3))) &&
(mpa->frame.frequency_index == (((tmp2 >> 10) & 3) + 3*(mpa->frame.LSF + mpa->frame.MPEG25))) &&
(mpa->frame.channels == ((((tmp2 >> 6) & 3) == MPG_MD_MONO) ? 1 : 2))) {
retval = tmp;
break;
}
}
}
}
} else {
retval = tmp;
break;
}
}
buf++; i--;
}
} else {
while (i >= 4) {
register uint32_t tmp = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
if (((tmp & 0xFFE00000) == 0xFFE00000) && (tmp & (3 << 17)) && ((tmp & (3 << 10)) != (3 << 10))) {
if ((mpa->frame.layer == (uint8_t)(4 - ((tmp >> 17) & 3))) &&
(mpa->frame.frequency_index == (((tmp >> 10) & 3) + 3*(mpa->frame.LSF + mpa->frame.MPEG25))) &&
(mpa->frame.channels == ((((tmp >> 6) & 3) == MPG_MD_MONO) ? 1 : 2))) {
retval = tmp;
break;
}
}
buf++; i--;
}
}
if (i < mpa->bytes_left) {
i = mpa->bytes_left - i;
mpa->next_byte = buf;;
mpa->bytes_left -= i;
if (i >= 512) {
mpa->reservoir_size = 0;
i = 512;
}
memcpy(mpa->reservoir + mpa->reservoir_size, mpa->next_byte - i, i);
mpa->reservoir_size += i;
}
return retval;
}
static int first_frame(mpadec_t mpadec)
{
register struct mpadec_t *mpa = (struct mpadec_t *)mpadec;
int i, skip = FALSE;
uint32_t framesize; FLOAT scale;
if (mpa->frame.channels > 1) i = ((mpa->config.mode == MPADEC_CONFIG_STEREO) || (mpa->config.mode == MPADEC_CONFIG_AUTO)) ? 3 : 2;
else i = (mpa->config.mode == MPADEC_CONFIG_STEREO) ? 1 : 0;
mpa->synth_func = synth_table[mpa->config.quality][mpa->config.endian][mpa->config.format][i];
mpa->sample_size = mpa->frame.decoded_channels;
switch (mpa->config.format) {
case MPADEC_CONFIG_24BIT: mpa->sample_size *= 3; scale = 0x800000; break;
case MPADEC_CONFIG_32BIT: mpa->sample_size <<= 2; scale = 0x80000000; break;
case MPADEC_CONFIG_FLOAT: mpa->sample_size <<= 2; scale = 1; break;
default: mpa->sample_size <<= 1; scale = 0x8000; break;
}
mpa->synth_size = (mpa->sample_size << 5) >> mpa->config.quality;
if (mpa->config.replaygain != MPADEC_CONFIG_REPLAYGAIN_CUSTOM) {
mpa->config.gain = 0.0;
mpa->replay_gain = 1.0;
}
mpa->skip_samples = 0;
mpa->padding_samples = 0;
mpa->decoded_frames = 0;
mpa->decoded_samples = 0;
memset(&mpa->tag_info, 0, sizeof(mpa->tag_info));
framesize = (mpa->frame.frame_size < mpa->bytes_left) ? mpa->frame.frame_size : mpa->bytes_left;
if ((mpa->frame.layer == 3) && (framesize >= (mpa->ssize + 124))) {
register uint8_t *buf = mpa->next_byte + 4 + mpa->ssize;
if (((buf[0] == 'X') && (buf[1] == 'i') && (buf[2] == 'n') && (buf[3] == 'g')) ||
((buf[0] == 'I') && (buf[1] == 'n') && (buf[2] == 'f') && (buf[3] == 'o'))) {
skip = TRUE;
mpa->next_byte += framesize;
mpa->bytes_left -= framesize;
buf += 4;
mpa->tag_info.flags = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
buf += 4;
if (mpa->tag_info.flags & 1) {
mpa->tag_info.frames = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
buf += 4;
};
if (mpa->tag_info.flags & 2) {
mpa->tag_info.bytes = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
buf += 4;
};
if (mpa->tag_info.flags & 4) {
memcpy(mpa->tag_info.toc, buf, 100);
buf += 100;
};
if (mpa->tag_info.flags & 8) buf += 4;
mpa->tag_info.flags &= 7;
if (framesize >= mpa->ssize + 160) {
buf += 15;
mpa->tag_info.replay_gain[0] = ((buf[0] << 8) | buf[1]) & 0x1FF;
if (buf[0] & 2) mpa->tag_info.replay_gain[0] = -mpa->tag_info.replay_gain[0];
buf += 2;
mpa->tag_info.replay_gain[1] = ((buf[0] << 8) | buf[1]) & 0x1FF;
if (buf[0] & 2) mpa->tag_info.replay_gain[1] = -mpa->tag_info.replay_gain[1];
buf += 4;
mpa->tag_info.enc_delay = (buf[0] << 4) | ((buf[1] >> 4) & 0x0F);
mpa->tag_info.enc_padding = ((buf[1] & 0x0F) << 8) | buf[2];
if (((mpa->tag_info.enc_delay < 0) || (mpa->tag_info.enc_delay > 3000)) ||
((mpa->tag_info.enc_padding < 0) || (mpa->tag_info.enc_padding > 3000))) {
mpa->tag_info.replay_gain[0] = mpa->tag_info.replay_gain[1] = 0;
mpa->tag_info.enc_delay = 0;
mpa->tag_info.enc_padding = 0;
} else {
if (mpa->config.replaygain == MPADEC_CONFIG_REPLAYGAIN_RADIO) {
mpa->config.gain = ((FLOAT)mpa->tag_info.replay_gain[0])/10.0;
} else if (mpa->config.replaygain == MPADEC_CONFIG_REPLAYGAIN_AUDIOPHILE) {
mpa->config.gain = ((FLOAT)mpa->tag_info.replay_gain[1])/10.0;
}
}
mpa->skip_samples = mpa->tag_info.enc_delay;
mpa->padding_samples = mpa->tag_info.enc_padding;
}
}
}
mpa->replay_gain = pow(10.0, mpa->config.gain/20.0);
if (mpa->config.replaygain != MPADEC_CONFIG_REPLAYGAIN_NONE) scale *= mpa->replay_gain;
init_tables(mpa, scale, SBLIMIT >> mpa->config.quality);
if (mpa->frame.layer == 3) {
mpa->skip_samples += 529;
if ((mpa->tag_info.flags & 1) && (mpa->padding_samples > 529)) mpa->padding_samples -= 529;
else mpa->padding_samples = 0;
} else {
mpa->skip_samples += 241;
mpa->padding_samples = 0;
}
mpa->padding_start = mpa->tag_info.frames*mpa->frame.frame_samples;
if (mpa->padding_start > mpa->padding_samples) mpa->padding_start -= mpa->padding_samples;
else mpa->padding_start = 0;
mpa->state = MPADEC_STATE_DECODE;
return skip;
}
mpadec_t MPADECAPI mpadec_init(void)
{
register struct mpadec_t *mpa = (struct mpadec_t *)malloc(sizeof(struct mpadec_t));
uint8_t temp[2];
if (!mpa) return NULL;
memset(mpa, 0, sizeof(struct mpadec_t));
mpa->size = sizeof(struct mpadec_t);
*((int16_t *)temp) = 1;
mpa->config.quality = MPADEC_CONFIG_FULL_QUALITY;
mpa->config.mode = MPADEC_CONFIG_AUTO;
mpa->config.format = MPADEC_CONFIG_16BIT;
mpa->config.endian = (uint8_t)((uint8_t)temp[0] ? MPADEC_CONFIG_LITTLE_ENDIAN : MPADEC_CONFIG_BIG_ENDIAN);
mpa->config.replaygain = MPADEC_CONFIG_REPLAYGAIN_NONE;
mpa->config.skip = TRUE;
mpa->config.crc = TRUE;
mpa->config.dblsync = TRUE;
mpa->config.gain = 0.0;
mpa->replay_gain = 1.0;
init_tables(mpa, 0x8000, SBLIMIT);
mpa->synth_bufoffs = 1;
mpa->state = MPADEC_STATE_START;
return mpa;
}
int MPADECAPI mpadec_uninit(mpadec_t mpadec)
{
register struct mpadec_t *mpa = (struct mpadec_t *)mpadec;
if (mpa && (mpa->size == sizeof(struct mpadec_t))) {
mpa->size = mpa->state = 0;
free(mpa);
return MPADEC_RETCODE_OK;
} else return MPADEC_RETCODE_INVALID_HANDLE;
}
int MPADECAPI mpadec_reset(mpadec_t mpadec)
{
register struct mpadec_t *mpa = (struct mpadec_t *)mpadec;
if (mpa && (mpa->size == sizeof(struct mpadec_t))) {
memset(mpa->hybrid_in, 0, sizeof(mpa->hybrid_in));
memset(mpa->hybrid_out, 0, sizeof(mpa->hybrid_out));
memset(mpa->hybrid_buffers, 0, sizeof(mpa->hybrid_buffers));
memset(mpa->synth_buffers, 0, sizeof(mpa->synth_buffers));
mpa->hybrid_block[0] = mpa->hybrid_block[1] = 0;
mpa->synth_bufoffs = 1;
memset(&mpa->tag_info, 0, sizeof(mpa->tag_info));
if (mpa->config.replaygain != MPADEC_CONFIG_REPLAYGAIN_CUSTOM) mpa->config.gain = 0.0;
mpa->prev_frame_size = 0;
mpa->free_format = FALSE;
mpa->error = FALSE;
mpa->reservoir_size = 0;
mpa->replay_gain = 1.0;
mpa->skip_samples = 0;
mpa->padding_samples = 0;
mpa->decoded_frames = 0;
mpa->decoded_samples = 0;
mpa->state = MPADEC_STATE_START;
return MPADEC_RETCODE_OK;
} else return MPADEC_RETCODE_INVALID_HANDLE;
}
int MPADECAPI mpadec_configure(mpadec_t mpadec, mpadec_config_t *cfg)
{
register struct mpadec_t *mpa = (struct mpadec_t *)mpadec;
int32_t i, sblimit; FLOAT scale;
if (mpa && (mpa->size == sizeof(struct mpadec_t))) {
if (!cfg) return MPADEC_RETCODE_INVALID_PARAMETERS;
if ((cfg->quality > MPADEC_CONFIG_HALF_QUALITY) || (cfg->mode > MPADEC_CONFIG_CHANNEL2) ||
(cfg->format > MPADEC_CONFIG_FLOAT) || (cfg->endian > MPADEC_CONFIG_BIG_ENDIAN) ||
(cfg->replaygain > MPADEC_CONFIG_REPLAYGAIN_CUSTOM)) return MPADEC_RETCODE_INVALID_PARAMETERS;
mpa->config.quality = cfg->quality;
mpa->config.mode = cfg->mode;
mpa->config.format = cfg->format;
mpa->config.endian = cfg->endian;
mpa->config.replaygain = cfg->replaygain;
mpa->config.skip = (uint8_t)(cfg->skip ? TRUE : FALSE);
mpa->config.crc = (uint8_t)(cfg->crc ? TRUE : FALSE);
mpa->config.dblsync = (uint8_t)(cfg->dblsync ? TRUE : FALSE);
if (mpa->config.replaygain == MPADEC_CONFIG_REPLAYGAIN_CUSTOM) {
mpa->config.gain = cfg->gain;
} else {
mpa->config.gain = 0.0;
if (mpa->tag_info.flags) {
if (mpa->config.replaygain == MPADEC_CONFIG_REPLAYGAIN_RADIO) {
mpa->config.gain = ((FLOAT)mpa->tag_info.replay_gain[0])/10.0;
} else if (mpa->config.replaygain == MPADEC_CONFIG_REPLAYGAIN_AUDIOPHILE) {
mpa->config.gain = ((FLOAT)mpa->tag_info.replay_gain[1])/10.0;
}
}
}
mpa->replay_gain = pow(10.0, mpa->config.gain/20.0);
switch (mpa->config.format) {
case MPADEC_CONFIG_24BIT: scale = 0x800000; break;
case MPADEC_CONFIG_32BIT: scale = 0x80000000; break;
case MPADEC_CONFIG_FLOAT: scale = 1; break;
default: scale = 0x8000; break;
}
sblimit = SBLIMIT >> mpa->config.quality;
if (mpa->config.replaygain != MPADEC_CONFIG_REPLAYGAIN_NONE) scale *= mpa->replay_gain;
init_tables(mpa, scale, sblimit);
if ((mpa->state > MPADEC_STATE_START) && mpa->header) {
decode_header(mpa, mpa->header);
if (mpa->frame.channels < 2) i = (mpa->config.mode == MPADEC_CONFIG_STEREO) ? 1 : 0;
else i = ((mpa->config.mode == MPADEC_CONFIG_STEREO) || (mpa->config.mode == MPADEC_CONFIG_AUTO)) ? 3 : 2;
mpa->synth_func = synth_table[mpa->config.quality][mpa->config.endian][mpa->config.format][i];
mpa->sample_size = mpa->frame.decoded_channels;
switch (mpa->config.format) {
case MPADEC_CONFIG_24BIT: mpa->sample_size *= 3; break;
case MPADEC_CONFIG_32BIT:
case MPADEC_CONFIG_FLOAT: mpa->sample_size <<= 2; break;
default: mpa->sample_size <<= 1; break;
}
mpa->synth_size = (mpa->sample_size << 5) >> mpa->config.quality;
} else mpa->state = MPADEC_STATE_START;
return MPADEC_RETCODE_OK;
} else return MPADEC_RETCODE_INVALID_HANDLE;
}
int MPADECAPI mpadec_get_info(mpadec_t mpadec, void *info, int info_type)
{
register struct mpadec_t *mpa = (struct mpadec_t *)mpadec;
if (!mpa || (mpa->size != sizeof(struct mpadec_t))) return MPADEC_RETCODE_INVALID_HANDLE;
if (!info) return MPADEC_RETCODE_INVALID_PARAMETERS;
if (info_type == MPADEC_INFO_CONFIG) {
register mpadec_config_t *cfg = (mpadec_config_t *)info;
cfg->quality = mpa->config.quality;
cfg->mode = mpa->config.mode;
cfg->format = mpa->config.format;
cfg->endian = mpa->config.endian;
cfg->replaygain = mpa->config.replaygain;
cfg->skip = mpa->config.skip;
cfg->crc = mpa->config.crc;
cfg->dblsync = mpa->config.dblsync;
cfg->gain = mpa->config.gain;
} else if (info_type == MPADEC_INFO_TAG) {
register mp3tag_info_t *tag = (mp3tag_info_t *)info;
if (mpa->state < MPADEC_STATE_DECODE) {
memset(tag, 0, sizeof(mp3tag_info_t));
return MPADEC_RETCODE_BAD_STATE;
} else memcpy(tag, &mpa->tag_info, sizeof(mpa->tag_info));
} else if (info_type == MPADEC_INFO_STREAM) {
register mpadec_info_t *inf = (mpadec_info_t *)info;
if (mpa->state < MPADEC_STATE_DECODE) {
memset(inf, 0, sizeof(mpadec_info_t));
return MPADEC_RETCODE_BAD_STATE;
} else {
inf->layer = mpa->frame.layer;
inf->channels = mpa->frame.channels;
inf->frequency = mpa->frame.frequency;
inf->bitrate = mpa->frame.bitrate;
inf->mode = mpa->frame.mode;
inf->copyright = mpa->frame.copyright;
inf->original = mpa->frame.original;
inf->emphasis = mpa->frame.emphasis;
inf->decoded_channels = mpa->frame.decoded_channels;
inf->decoded_frequency = mpa->frame.decoded_frequency;
inf->decoded_sample_size = mpa->sample_size;
inf->frame_size = mpa->frame.frame_size;
inf->frame_samples = mpa->frame.frame_samples;
inf->decoded_frame_samples = mpa->frame.decoded_samples;
if (mpa->tag_info.flags & 1) {
inf->frames = mpa->tag_info.frames;
inf->duration = (mpa->tag_info.frames*mpa->frame.frame_samples + (mpa->frame.frequency >> 1))/mpa->frame.frequency;
} else {
inf->frames = 0;
inf->duration = 0;
}
}
} else return MPADEC_RETCODE_INVALID_PARAMETERS;
return MPADEC_RETCODE_OK;
}
int MPADECAPI mpadec_decode(mpadec_t mpadec, uint8_t *srcbuf, uint32_t srcsize, uint8_t *dstbuf, uint32_t dstsize, uint32_t *srcused, uint32_t *dstused)
{
register struct mpadec_t *mpa = (struct mpadec_t *)mpadec;
int retcode = MPADEC_RETCODE_OK;
uint32_t decoded_size = 0;
if (srcused) *srcused = 0;
if (dstused) *dstused = 0;
if (!dstbuf) dstsize = 0;
if (!mpa || (mpa->size != sizeof(struct mpadec_t))) return MPADEC_RETCODE_INVALID_HANDLE;
if (mpa->state < MPADEC_STATE_START) return MPADEC_RETCODE_BAD_STATE;
if (!srcbuf || ((mpa->state > MPADEC_STATE_START) && !dstbuf )) return MPADEC_RETCODE_INVALID_PARAMETERS;
mpa->next_byte = srcbuf;
mpa->bytes_left = srcsize;
while (mpa->bytes_left >= 4) {
mpa->error = FALSE;
mpa->bits_left = 0;
mpa->header = sync_buffer(mpa);
if (!mpa->header) {
if (!decoded_size) retcode = MPADEC_RETCODE_NO_SYNC;
break;
}
decode_header(mpa, mpa->header);
if ((mpa->bytes_left < mpa->frame.frame_size) || (mpa->free_format && !mpa->prev_frame_size)) {
retcode = MPADEC_RETCODE_NEED_MORE_DATA;
break;
}
if (mpa->state == MPADEC_STATE_START) {
if (first_frame(mpa)) continue;
} else if ((mpa->frame.layer == 3) && (mpa->frame.frame_size >= (mpa->ssize + 12))) {
register uint8_t *buf = mpa->next_byte + 4 + mpa->ssize;
if (((buf[0] == 'X') && (buf[1] == 'i') && (buf[2] == 'n') && (buf[3] == 'g')) ||
((buf[0] == 'I') && (buf[1] == 'n') && (buf[2] == 'f') && (buf[3] == 'o'))) {
mpa->next_byte += mpa->frame.frame_size;
mpa->bytes_left -= mpa->frame.frame_size;
continue;
}
}
if (dstsize < mpa->frame.decoded_size) {
retcode = MPADEC_RETCODE_BUFFER_TOO_SMALL;
break;
}
if (mpa->config.crc && mpa->frame.CRC) {
mpa->frame.crc = (uint16_t)((mpa->next_byte[4] << 8) | mpa->next_byte[5]);
mpa->crc = update_crc(0xFFFF, mpa->next_byte + 2, 16);
}
mpa->next_byte += mpa->hsize;
mpa->bytes_left -= mpa->hsize;
switch (mpa->frame.layer) {
case 1: decode_layer1(mpa, dstbuf); break;
case 2: decode_layer2(mpa, dstbuf); break;
case 3: decode_layer3(mpa, dstbuf); break;
}
if (mpa->config.crc && mpa->error) memset(dstbuf, 0, mpa->frame.decoded_size);
dstbuf += mpa->frame.decoded_size;
dstsize -= mpa->frame.decoded_size;
decoded_size += mpa->frame.decoded_size;
mpa->decoded_samples += mpa->frame.frame_samples;
mpa->decoded_frames++;
if (mpa->config.skip) {
if (mpa->skip_samples) {
if (mpa->skip_samples >= mpa->frame.frame_samples) {
dstbuf -= mpa->frame.decoded_size;
dstsize += mpa->frame.decoded_size;
decoded_size -= mpa->frame.decoded_size;
mpa->skip_samples -= mpa->frame.frame_samples;
} else {
uint32_t tmp = mpa->frame.frame_samples - mpa->skip_samples;
tmp = mpa->sample_size*(tmp >> mpa->config.quality);
memmove(dstbuf - mpa->frame.decoded_size, dstbuf - tmp, tmp);
dstbuf -= mpa->frame.decoded_size - tmp;
dstsize += mpa->frame.decoded_size - tmp;
decoded_size -= mpa->frame.decoded_size - tmp;
mpa->skip_samples = 0;
}
} else if ((mpa->padding_samples) && (mpa->decoded_samples > mpa->padding_start)) {
uint32_t tmp = mpa->decoded_samples - mpa->padding_start;
if (tmp > mpa->padding_samples) tmp = mpa->padding_samples;
mpa->padding_start += tmp;
mpa->padding_samples -= tmp;
tmp = mpa->sample_size*(tmp >> mpa->config.quality);
dstbuf -= tmp;
dstsize += tmp;
decoded_size -= tmp;
}
}
}
if (srcused) *srcused = srcsize - mpa->bytes_left;
if (dstused) *dstused = decoded_size;
if ((retcode == MPADEC_RETCODE_OK) && mpa->bytes_left) retcode = MPADEC_RETCODE_NEED_MORE_DATA;
if (!dstbuf && (retcode == MPADEC_RETCODE_BUFFER_TOO_SMALL)) retcode = MPADEC_RETCODE_OK;
return retcode;
}
char * MPADECAPI mpadec_error(int code)
{
static char *mpa_errors[] = { "No error",
"Invalid handle",
"Not enough memory",
"Bad decoder state",
"Invalid parameters",
"Need more data",
"Output buffer too small",
"Unable to synchronize",
"Unknown error" };
if (code > MPADEC_RETCODE_UNKNOWN) code = MPADEC_RETCODE_UNKNOWN;
return mpa_errors[code];
}
mpadec2_t MPADECAPI mpadec2_init(void)
{
register struct mpadec2_t *mpa = (struct mpadec2_t *)malloc(sizeof(struct mpadec2_t));
if (!mpa) return NULL;
mpa->size = sizeof(struct mpadec2_t);
mpa->buffers = NULL;
mpa->in_buffer_offset = mpa->in_buffer_used = 0;
mpa->out_buffer_offset = mpa->out_buffer_used = 0;
mpa->mpadec = mpadec_init();
if (!mpa->mpadec) {
free(mpa);
return NULL;
}
return mpa;
}
int MPADECAPI mpadec2_uninit(mpadec2_t mpadec)
{
register struct mpadec2_t *mpa = (struct mpadec2_t *)mpadec;
if (mpa && (mpa->size == sizeof(struct mpadec2_t))) {
struct mpabuffer_t *buf = mpa->buffers, *tmp;
while (buf) {
tmp = buf;
buf = buf->next;
free(tmp);
}
mpadec_uninit(mpa->mpadec);
free(mpa);
return MPADEC_RETCODE_OK;
} else return MPADEC_RETCODE_INVALID_HANDLE;
}
int MPADECAPI mpadec2_reset(mpadec2_t mpadec)
{
register struct mpadec2_t *mpa = (struct mpadec2_t *)mpadec;
if (mpa && (mpa->size == sizeof(struct mpadec2_t))) {
struct mpabuffer_t *buf = mpa->buffers, *tmp;
while (buf) {
tmp = buf;
buf = buf->next;
free(tmp);
}
mpa->buffers = NULL;
mpa->in_buffer_offset = mpa->in_buffer_used = 0;
mpa->out_buffer_offset = mpa->out_buffer_used = 0;
mpadec_reset(mpa->mpadec);
return MPADEC_RETCODE_OK;
} else return MPADEC_RETCODE_INVALID_HANDLE;
}
int MPADECAPI mpadec2_configure(mpadec2_t mpadec, mpadec_config_t *cfg)
{
register struct mpadec2_t *mpa = (struct mpadec2_t *)mpadec;
if (!mpa || (mpa->size != sizeof(struct mpadec2_t))) return MPADEC_RETCODE_INVALID_HANDLE;
mpa->out_buffer_offset = mpa->out_buffer_used = 0;
return (mpadec_configure(mpa->mpadec, cfg));
}
int MPADECAPI mpadec2_get_info(mpadec2_t mpadec, void *info, int info_type)
{
register struct mpadec2_t *mpa = (struct mpadec2_t *)mpadec;
if (!mpa || (mpa->size != sizeof(struct mpadec2_t))) return MPADEC_RETCODE_INVALID_HANDLE;
return (mpadec_get_info(mpa->mpadec, info, info_type));
}
int MPADECAPI mpadec2_decode(mpadec2_t mpadec, uint8_t *srcbuf, uint32_t srcsize, uint8_t *dstbuf, uint32_t dstsize, uint32_t *dstused)
{
register struct mpadec2_t *mpa = (struct mpadec2_t *)mpadec;
uint32_t n, src_used, dst_used; int r;
if (dstused) *dstused = 0;
if (!mpa || (mpa->size != sizeof(struct mpadec2_t))) return MPADEC_RETCODE_INVALID_HANDLE;
if (((struct mpadec_t *)mpa->mpadec)->state < MPADEC_STATE_START) return MPADEC_RETCODE_BAD_STATE;
if (srcbuf && srcsize) {
struct mpabuffer_t *last = mpa->buffers, *buf;
if (last) {
while (last->next) last = last->next;
if ((last->offset + last->used) < last->size) {
n = last->size - (last->offset + last->used);
if (n > srcsize) n = srcsize;
memcpy(last->buffer + last->offset + last->used, srcbuf, n);
last->used += n;
srcbuf += n;
srcsize -= n;
}
}
if (srcsize) {
n = (srcsize > 4096) ? srcsize : 4096;
buf = (struct mpabuffer_t *)malloc(n + sizeof(struct mpabuffer_t));
if (buf) {
buf->size = n;
buf->offset = buf->used = 0;
buf->buffer = (uint8_t *)buf + sizeof(struct mpabuffer_t);
buf->next = NULL;
memcpy(buf->buffer, srcbuf, srcsize);
buf->used = srcsize;
if (last) last->next = buf; else mpa->buffers = buf;
} else return MPADEC_RETCODE_NOT_ENOUGH_MEMORY;
}
}
if (!dstbuf || !dstsize) return MPADEC_RETCODE_OK;
while (dstsize) {
struct mpabuffer_t *buf = mpa->buffers;
if (mpa->out_buffer_used) {
n = (dstsize < mpa->out_buffer_used) ? dstsize : mpa->out_buffer_used;
memcpy(dstbuf, mpa->out_buffer + mpa->out_buffer_offset, n);
mpa->out_buffer_offset += n;
mpa->out_buffer_used -= n;
dstbuf += n;
dstsize -= n;
if (dstused) *dstused += n;
}
if (!dstsize) break;
if (mpa->in_buffer_used && mpa->in_buffer_offset) memmove(mpa->in_buffer, mpa->in_buffer + mpa->in_buffer_offset, mpa->in_buffer_used);
mpa->in_buffer_offset = 0;
while (buf && (mpa->in_buffer_used < sizeof(mpa->in_buffer))) {
if (buf->used) {
n = sizeof(mpa->in_buffer) - mpa->in_buffer_used;
if (n > buf->used) n = buf->used;
memcpy(mpa->in_buffer + mpa->in_buffer_offset + mpa->in_buffer_used, buf->buffer + buf->offset, n);
buf->offset += n;
buf->used -= n;
mpa->in_buffer_used += n;
}
if (!buf->used) {
struct mpabuffer_t *tmp = buf;
buf = buf->next;
free(tmp);
}
}
mpa->buffers = buf;
r = mpadec_decode(mpa->mpadec, mpa->in_buffer + mpa->in_buffer_offset, mpa->in_buffer_used, dstbuf, dstsize, &src_used, &dst_used);
mpa->in_buffer_offset += src_used;
mpa->in_buffer_used -= src_used;
dstbuf += dst_used;
dstsize -= dst_used;
if (dstused) *dstused += dst_used;
if (r == MPADEC_RETCODE_BUFFER_TOO_SMALL) {
mpa->out_buffer_offset = mpa->out_buffer_used = 0;
mpadec_decode(mpa->mpadec, mpa->in_buffer + mpa->in_buffer_offset, mpa->in_buffer_used, mpa->out_buffer, sizeof(mpa->out_buffer), &src_used, &mpa->out_buffer_used);
mpa->in_buffer_offset += src_used;
mpa->in_buffer_used -= src_used;
if (!mpa->out_buffer_used) break;
} else if (!mpa->buffers) break;
}
return MPADEC_RETCODE_OK;
}