Got a basic MP3 Decoder working.

Commented out debug console output in mpaudec.
This commit is contained in:
Joshua Jones 2010-02-12 23:11:26 +00:00
parent f0a5c7411d
commit e5fa03d1d6
3 changed files with 234 additions and 46 deletions

View File

@ -1,22 +1,108 @@
#include "cMP3Decoder.h"
#include <stdlib.h>
#include <string.h>
cMP3Decoder::cMP3Decoder(IDataSource* stream) : IAudioDecoder(stream)
cMP3Decoder::cMP3Decoder(IDataSource* stream) : IAudioDecoder(stream), Context(0x0),
Valid(false), DataOffset(0), NumChannels(0), Frequency(0)
{
if(Stream && Stream->isValid() && Stream->getSize() > 0)
{
CurrentPacket.data = new unsigned char[MPAUDEC_MAX_AUDIO_FRAME_SIZE];
if(!CurrentPacket.data)
return;
Context = new MPAuDecContext();
if(!Context || mpaudec_init(Context) < 0)
{
delete Context;
Context = 0x0;
return;
}
//Check to see if we need to skip the idv3 header
char idv3Header[10];
int amountRead = Stream->read(idv3Header, 10);
if (amountRead == 10 && idv3Header[0] == 'I' && idv3Header[1] == 'D' && idv3Header[2] == '3')
{
int versionMajor = idv3Header[3];
int versionMinor = idv3Header[4];
int flags = idv3Header[5];
int size = 0;
size = (idv3Header[6] & 0x7f) << (3*7);
size |= (idv3Header[7] & 0x7f) << (2*7);
size |= (idv3Header[8] & 0x7f) << (1*7);
size |= (idv3Header[9] & 0x7f) ;
size += 10; // header size
DataOffset = size;
Stream->seek(DataOffset, false);
}
else
{
Stream->seek(0, false);
}
//Now, read the header for our information
Context->parse_only = 1;
unsigned char tempBuffer[MPAUDEC_MAX_AUDIO_FRAME_SIZE];
int outputSize = 0;
unsigned char inputBuffer[4096];
int inputSize = Stream->read(inputBuffer, 4096);
int rv = mpaudec_decode_frame( Context, tempBuffer, &outputSize, inputBuffer, inputSize);
//Oops, error...
if(rv < 0)
return;
NumChannels = Context->channels;
Frequency = Context->sample_rate;
Context->parse_only = 0;
Stream->seek(DataOffset, false);
Valid = true;
}
}
cMP3Decoder::~cMP3Decoder()
{
if (Context)
{
mpaudec_clear(Context);
delete Context;
}
if(CurrentPacket.data)
delete CurrentPacket.data;
}
AudioFormats cMP3Decoder::getFormat()
{
return EAF_16BIT_STEREO;
if(Valid)
{
if(NumChannels == 1)
{
return EAF_16BIT_MONO;
}
else
{
return EAF_16BIT_STEREO;
}
}
return EAF_8BIT_MONO;
}
int cMP3Decoder::getFrequency()
{
if(Valid)
{
return Frequency;
}
return 0;
}
@ -27,16 +113,90 @@ bool cMP3Decoder::isSeekingSupported()
bool cMP3Decoder::isValid()
{
return false;
return Valid;
}
int cMP3Decoder::readAudioData(void* output, int amount)
{
//Check to see if we have an empty packet and fill it
if(CurrentPacket.size <= CurrentPacket.read)
{
//Empty packet, grab a new one.
CurrentPacket.reset();
memset(CurrentPacket.data, 0, MPAUDEC_MAX_AUDIO_FRAME_SIZE);
unsigned char inputBuffer[4096];
int oldPos = Stream->getCurrentPos();
int inputSize = Stream->read(inputBuffer, Context->frame_size);
if(inputSize == 0)
return 0;
int rv = mpaudec_decode_frame( Context, CurrentPacket.data, &CurrentPacket.size, inputBuffer, inputSize);
Stream->seek(oldPos + rv, false);
//Oops, error...
if(rv < 0)
return -1;
//OpenAL really hates it if you try to change format in the middle
if(NumChannels != Context->channels)
return -1;
if(Frequency != Context->sample_rate)
return -1;
//Error from reading, but we need to try to move ahead to avoid stopping the feed since it may be recoverable
if(CurrentPacket.size < 0)
{
CurrentPacket.size = Context->frame_size;
memset(CurrentPacket.data, 0, CurrentPacket.size);
}
}
//If we have data left since last time, put it in if we have space
if( CurrentPacket.size > CurrentPacket.read )
{
int amountLeft = CurrentPacket.size - CurrentPacket.read;
if(amountLeft < amount)
{
//Dump in all our data
memcpy(output, CurrentPacket.data + CurrentPacket.read, amountLeft);
CurrentPacket.read += amountLeft;
return amountLeft;
}
else
{
//Not enough space for all our data, put in a little bit
memcpy(output, CurrentPacket.data + CurrentPacket.read, amount);
CurrentPacket.read += amount;
return amount;
}
}
return 0;
}
bool cMP3Decoder::setPosition(int position, bool relative)
{
if(position == 0 && !relative)
{
//Just reload from scratch
Stream->seek(DataOffset, false);
MPAuDecContext oldContext = *Context;
mpaudec_clear(Context);
mpaudec_init(Context);
Context->bit_rate = oldContext.bit_rate;
Context->channels = oldContext.channels;
Context->frame_size = oldContext.frame_size;
Context->sample_rate = oldContext.sample_rate;
return true;
}
return false;
}

View File

@ -2,9 +2,29 @@
#define CMP3DECODER_H
#include "IAudioDecoder.h"
#include "mpaudec/mpaudec.h"
using namespace cAudio;
class cMP3Packet
{
public:
cMP3Packet()
{
data = 0x0;
reset();
}
void reset()
{
size = 0;
read = 0;
}
int size;
int read;
unsigned char* data;
};
class cMP3Decoder : public IAudioDecoder
{
public:
@ -31,6 +51,15 @@ class cMP3Decoder : public IAudioDecoder
//!If seeking is supported, will seek the stream to seconds
virtual bool seek(float seconds, bool relative);
protected:
MPAuDecContext* Context;
bool Valid;
unsigned int DataOffset;
int NumChannels;
int Frequency;
cMP3Packet CurrentPacket;
};
#endif //! CMP3DECODER_H

View File

@ -20,7 +20,6 @@
* stand-alone mpaudec library. Based on mpegaudiodec.c from libavcodec.
*/
/*#define DEBUG*/
#include "internal.h"
#include "mpegaudio.h"
@ -333,13 +332,13 @@ int mpaudec_init(MPAuDecContext * mpctx)
scale_factor_mult[i][0] = MULL(FIXR(1.0 * 2.0), norm);
scale_factor_mult[i][1] = MULL(FIXR(0.7937005259 * 2.0), norm);
scale_factor_mult[i][2] = MULL(FIXR(0.6299605249 * 2.0), norm);
#ifdef DEBUG
/*#ifdef DEBUG
printf("%d: norm=%x s=%x %x %x\n",
i, norm,
scale_factor_mult[i][0],
scale_factor_mult[i][1],
scale_factor_mult[i][2]);
#endif
#endif*/
}
/* window */
@ -429,10 +428,10 @@ int mpaudec_init(MPAuDecContext * mpctx)
k = i & 1;
is_table_lsf[j][k ^ 1][i] = FIXR(f);
is_table_lsf[j][k][i] = FIXR(1.0);
#ifdef DEBUG
/*#ifdef DEBUG
printf("is_table_lsf %d %d: %x %x\n",
i, j, is_table_lsf[j][0][i], is_table_lsf[j][1][i]);
#endif
#endif*/
}
}
@ -475,14 +474,14 @@ int mpaudec_init(MPAuDecContext * mpctx)
}
}
#if defined(DEBUG)
/*#if defined(DEBUG)
for(j=0;j<8;j++) {
printf("win%d=\n", j);
for(i=0;i<36;i++)
printf("%f, ", (double)mdct_win[j][i] / FRAC_ONE);
printf("\n");
}
#endif
#endif*/
init = 1;
}
@ -1150,7 +1149,7 @@ static int decode_header(MPADecodeContext *s, uint32_t header)
}
}
#if defined(DEBUG)
/*#if defined(DEBUG)
printf("layer%d, %d Hz, %d kbits/s, ",
s->layer, s->sample_rate, s->bit_rate);
if (s->nb_channels == 2) {
@ -1165,7 +1164,7 @@ static int decode_header(MPADecodeContext *s, uint32_t header)
printf("mono");
}
printf("\n");
#endif
#endif*/
return 0;
}
@ -1279,9 +1278,9 @@ static int mp_decode_layer2(MPADecodeContext *s)
else
bound = sblimit;
#ifdef DEBUG
/*#ifdef DEBUG
printf("bound=%d sblimit=%d\n", bound, sblimit);
#endif
#endif*/
/* parse bit allocation */
j = 0;
for(i=0;i<bound;i++) {
@ -1299,7 +1298,7 @@ static int mp_decode_layer2(MPADecodeContext *s)
j += 1 << bit_alloc_bits;
}
#ifdef DEBUG
/*#ifdef DEBUG
{
for(ch=0;ch<s->nb_channels;ch++) {
for(i=0;i<sblimit;i++)
@ -1307,7 +1306,7 @@ static int mp_decode_layer2(MPADecodeContext *s)
printf("\n");
}
}
#endif
#endif*/
/* scale codes */
for(i=0;i<sblimit;i++) {
@ -1349,7 +1348,7 @@ static int mp_decode_layer2(MPADecodeContext *s)
}
}
#ifdef DEBUG
/*#ifdef DEBUG
for(ch=0;ch<s->nb_channels;ch++) {
for(i=0;i<sblimit;i++) {
if (bit_alloc[ch][i]) {
@ -1361,7 +1360,7 @@ static int mp_decode_layer2(MPADecodeContext *s)
}
printf("\n");
}
#endif
#endif*/
/* samples */
for(k=0;k<3;k++) {
@ -1593,10 +1592,10 @@ static int huffman_decode(MPADecodeContext *s, GranuleDef *g,
x = 0;
y = 0;
}
#ifdef DEBUG
/*#ifdef DEBUG
printf("region=%d n=%d x=%d y=%d exp=%d\n",
i, g->region_size[i] - j, x, y, exponents[s_index]);
#endif
#endif*/
if (x) {
if (x == 15)
x += get_bitsz(&s->gb, linbits);
@ -1637,9 +1636,9 @@ static int huffman_decode(MPADecodeContext *s, GranuleDef *g,
last_gb= s->gb;
code = get_vlc(&s->gb, vlc);
#ifdef DEBUG
/*#ifdef DEBUG
printf("t=%d code=%d\n", g->count1table_select, code);
#endif
#endif*/
if (code < 0)
return -1;
for(i=0;i<4;i++) {
@ -1990,9 +1989,9 @@ static int mp_decode_layer3(MPADecodeContext *s)
for(gr=0;gr<nb_granules;gr++) {
for(ch=0;ch<s->nb_channels;ch++) {
#ifdef DEBUG
/*#ifdef DEBUG
printf("gr=%d ch=%d: side_info\n", gr, ch);
#endif
#endif*/
g = &granules[ch][gr];
g->part2_3_length = get_bits(&s->gb, 12);
g->big_values = get_bits(&s->gb, 9);
@ -2037,10 +2036,10 @@ static int mp_decode_layer3(MPADecodeContext *s)
/* compute huffman coded region sizes */
region_address1 = get_bits(&s->gb, 4);
region_address2 = get_bits(&s->gb, 3);
#ifdef DEBUG
/*#ifdef DEBUG
printf("region1=%d region2=%d\n",
region_address1, region_address2);
#endif
#endif*/
g->region_size[0] =
band_index_long[s->sample_rate_index][region_address1 + 1] >> 1;
l = region_address1 + region_address2 + 2;
@ -2093,17 +2092,17 @@ static int mp_decode_layer3(MPADecodeContext *s)
g->preflag = get_bits(&s->gb, 1);
g->scalefac_scale = get_bits(&s->gb, 1);
g->count1table_select = get_bits(&s->gb, 1);
#ifdef DEBUG
/*#ifdef DEBUG
printf("block_type=%d switch_point=%d\n",
g->block_type, g->switch_point);
#endif
#endif*/
}
}
/* now we get bits from the main_data_begin offset */
#ifdef DEBUG
/*#ifdef DEBUG
printf("seekback: %d\n", main_data_begin);
#endif
#endif*/
seek_to_maindata(s, main_data_begin);
for(gr=0;gr<nb_granules;gr++) {
@ -2119,9 +2118,9 @@ static int mp_decode_layer3(MPADecodeContext *s)
/* MPEG1 scale factors */
slen1 = slen_table[0][g->scalefac_compress];
slen2 = slen_table[1][g->scalefac_compress];
#ifdef DEBUG
/*#ifdef DEBUG
printf("slen1=%d slen2=%d\n", slen1, slen2);
#endif
#endif*/
if (g->block_type == 2) {
n = g->switch_point ? 17 : 18;
j = 0;
@ -2150,7 +2149,7 @@ static int mp_decode_layer3(MPADecodeContext *s)
}
g->scale_factors[j++] = 0;
}
#if defined(DEBUG)
/*#if defined(DEBUG)
{
printf("scfsi=%x gr=%d ch=%d scale_factors:\n",
g->scfsi, gr, ch);
@ -2158,7 +2157,7 @@ static int mp_decode_layer3(MPADecodeContext *s)
printf(" %d", g->scale_factors[i]);
printf("\n");
}
#endif
#endif*/
} else {
int tindex, tindex2, slen[4], sl, sf;
@ -2207,7 +2206,7 @@ static int mp_decode_layer3(MPADecodeContext *s)
/* XXX: should compute exact size */
for(;j<40;j++)
g->scale_factors[j] = 0;
#if defined(DEBUG)
/*#if defined(DEBUG)
{
printf("gr=%d ch=%d scale_factors:\n",
gr, ch);
@ -2215,7 +2214,7 @@ static int mp_decode_layer3(MPADecodeContext *s)
printf(" %d", g->scale_factors[i]);
printf("\n");
}
#endif
#endif*/
}
exponents_from_scale_factors(s, g, exponents);
@ -2228,9 +2227,9 @@ static int mp_decode_layer3(MPADecodeContext *s)
/* skip extension bits */
bits_left = g->part2_3_length - (get_bits_count(&s->gb) - bits_pos);
if (bits_left < 0) {
#ifdef DEBUG
/*#ifdef DEBUG
printf("bits_left=%d\n", bits_left);
#endif
#endif*/
return -1;
}
while (bits_left >= 16) {
@ -2268,9 +2267,9 @@ static int mp_decode_frame(MPADecodeContext *s,
if (s->error_protection)
get_bits(&s->gb, 16);
#ifdef DEBUG
/*#ifdef DEBUG
printf("frame %d:\n", s->frame_count);
#endif
#endif*/
switch(s->layer) {
case 1:
nb_frames = mp_decode_layer1(s);
@ -2283,7 +2282,7 @@ static int mp_decode_frame(MPADecodeContext *s,
nb_frames = mp_decode_layer3(s);
break;
}
#if defined(DEBUG)
/*#if defined(DEBUG)
for(i=0;i<nb_frames;i++) {
for(ch=0;ch<s->nb_channels;ch++) {
int j;
@ -2293,7 +2292,7 @@ static int mp_decode_frame(MPADecodeContext *s,
printf("\n");
}
}
#endif
#endif*/
/* apply the synthesis filter */
for(ch=0;ch<s->nb_channels;ch++) {
samples_ptr = samples + ch;
@ -2345,9 +2344,9 @@ int mpaudec_decode_frame(MPAuDecContext * mpctx,
/* no sync found : move by one byte (inefficient, but simple!) */
memmove(s->inbuf, s->inbuf + 1, s->inbuf_ptr - s->inbuf - 1);
s->inbuf_ptr--;
#ifdef DEBUG
/*#ifdef DEBUG
printf("skip %x\n", header);
#endif
#endif*/
/* reset free format frame size to give a chance
to get a new bitrate */
s->free_format_frame_size = 0;
@ -2418,10 +2417,10 @@ int mpaudec_decode_frame(MPAuDecContext * mpctx,
s->free_format_frame_size -= padding * 4;
else
s->free_format_frame_size -= padding;
#ifdef DEBUG
/*#ifdef DEBUG
printf("free frame size=%d padding=%d\n",
s->free_format_frame_size, padding);
#endif
#endif*/
decode_header(s, header1);
} else
p++;