/*------------------------------------------------------------------------
*
* Copyright (c) 1997-1998 by Cornell University.
*
* See the file "license.txt" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* mp123dec.c
*
* Ooi Wei Tsang weitsang@cs.cornell.edu
*
* Usage : mp123dec inputMPG outputPCM
*
* Decodes an input MPEG-1 Audio (layer 1, 2 or 3) into a PCM file.
* It assumes that all frames in the audio are encoded using the same
* layer encoding method.
*
* NOTE : Currently we output each frame to file after decoding, this
* is not the most efficient way of doing things.
*
*------------------------------------------------------------------------
*/
#include "dvmbasic.h"
#include "dvmmpeg.h"
/*
* Ensures that there are at least size bytes of unprocessed data in
* the BitStream bs. If there is not enough data, processed data in
* the BitStream are thrown away, unprocessed data are shifted to the
* front, new data are read from file and appended to the current
* unprocessed data.
*/
void CheckBitStreamUnderflow(bs, bp, file, size)
BitStream *bs;
BitParser *bp;
FILE *file;
int size;
{
int off = BitParserTell(bp);
int left = BitStreamBytesLeft(bs, off);
if (left < size) {
BitStreamShift(bs, off);
BitStreamFileRead(bs, file, left);
BitParserSeek(bp, 0);
}
}
/*
* This is the main routine that decodes a layer 1 audio file.
*/
void DecodeLayer1 (inbs, inbp, inf, outbs, outbp, outf, hdr)
BitStream *inbs;
BitParser *inbp;
FILE *inf;
BitStream *outbs;
BitParser *outbp;
FILE *outf;
MpegAudioHdr *hdr;
{
MpegAudioSynData *lv, *rv;
Audio *left, *right, *merge;
MpegAudioL1 *laudio, *raudio;
BitStream *tout;
int len;
/*
* Initialize various data structure.
* Each layer 1 frames contains 384 samples from each channel.
*/
lv = MpegAudioSynDataNew();
rv = MpegAudioSynDataNew();
left = Audio16New(384);
right = Audio16New(384);
merge = Audio16New(768);
laudio = MpegAudioL1New();
raudio = MpegAudioL1New();
/*
* Decode the first frame and output it to file.
*/
if (MpegAudioHdrGetMode(hdr) == MPEG_AUDIO_SINGLE_CHANNEL) {
MpegAudioL1MonoParse(inbp, hdr, laudio);
MpegAudioL1ToAudio(hdr, laudio, lv, left);
tout = Audio16CastToBitStream(left);
BitStreamFileWriteSegment(tout, outf, 0, 768);
} else {
MpegAudioL1StereoParse(inbp, hdr, laudio, raudio);
MpegAudioL1ToAudio(hdr, laudio, lv, left);
MpegAudioL1ToAudio(hdr, raudio, rv, right);
Audio16Merge(left, right, merge);
tout = Audio16CastToBitStream(merge);
BitStreamFileWriteSegment(tout, outf, 0, 1536);
}
BitStreamFree(tout);
len = MpegAudioHdrFind(inbp);
/*
* Repeatedly parse a frame header, parse a frame, decode the frame
* and output the samples to file, until we are done with all data.
*/
while (!feof(inf) || len != -1) {
CheckBitStreamUnderflow(inbs, inbp, inf, 2048);
MpegAudioHdrParse(inbp, hdr);
if (MpegAudioHdrGetMode(hdr) == MPEG_AUDIO_SINGLE_CHANNEL) {
MpegAudioL1MonoParse(inbp, hdr, laudio);
MpegAudioL1ToAudio(hdr, laudio, lv, left);
tout = Audio16CastToBitStream(left);
BitStreamFileWriteSegment(tout, outf, 0, 768);
} else {
MpegAudioL1StereoParse(inbp, hdr, laudio, raudio);
MpegAudioL1ToAudio(hdr, laudio, lv, left);
MpegAudioL1ToAudio(hdr, raudio, rv, right);
Audio16Merge(left, right, merge);
tout = Audio16CastToBitStream(merge);
BitStreamFileWriteSegment(tout, outf, 0, 1536);
}
BitStreamFree(tout);
len = MpegAudioHdrFind(inbp);
}
MpegAudioL1Free(laudio);
MpegAudioL1Free(raudio);
AudioFree(left);
AudioFree(right);
AudioFree(merge);
MpegAudioSynDataFree(lv);
MpegAudioSynDataFree(rv);
}
void DecodeLayer2 (inbs, inbp, inf, outbs, outbp, outf, hdr)
BitStream *inbs;
BitParser *inbp;
FILE *inf;
BitStream *outbs;
BitParser *outbp;
FILE *outf;
MpegAudioHdr *hdr;
{
MpegAudioSynData *lv, *rv;
Audio *left, *right, *merge;
MpegAudioL2 *laudio, *raudio;
BitStream *tout;
int len;
/*
* Initialize various data structure.
* Each layer 1 frames contains 1152 samples from each channel.
*/
lv = MpegAudioSynDataNew();
rv = MpegAudioSynDataNew();
left = Audio16New(1152);
right = Audio16New(1152);
merge = Audio16New(2304);
laudio = MpegAudioL2New();
raudio = MpegAudioL2New();
/*
* Decode the first frame and output it to file.
*/
if (MpegAudioHdrGetMode(hdr) == MPEG_AUDIO_SINGLE_CHANNEL) {
MpegAudioL2MonoParse(inbp, hdr, laudio);
MpegAudioL2ToAudio(hdr, laudio, lv, left);
tout = Audio16CastToBitStream(left);
BitStreamFileWriteSegment(tout, outf, 0, 2304);
} else {
MpegAudioL2StereoParse(inbp, hdr, laudio, raudio);
MpegAudioL2ToAudio(hdr, laudio, lv, left);
MpegAudioL2ToAudio(hdr, raudio, rv, right);
Audio16Merge(left, right, merge);
tout = Audio16CastToBitStream(merge);
BitStreamFileWriteSegment(tout, outf, 0, 4608);
}
BitStreamFree(tout);
len = MpegAudioHdrFind(inbp);
/*
* Repeatedly parse a frame header, parse a frame, decode the frame
* and output the samples to file, until we are done with all data.
*/
while (!feof(inf) || len != -1) {
CheckBitStreamUnderflow(inbs, inbp, inf, 4500);
MpegAudioHdrParse(inbp, hdr);
if (MpegAudioHdrGetMode(hdr) == MPEG_AUDIO_SINGLE_CHANNEL) {
MpegAudioL2MonoParse(inbp, hdr, laudio);
MpegAudioL2ToAudio(hdr, laudio, lv, left);
tout = Audio16CastToBitStream(left);
BitStreamFileWriteSegment(tout, outf, 0, 2304);
} else {
MpegAudioL2StereoParse(inbp, hdr, laudio, raudio);
MpegAudioL2ToAudio(hdr, laudio, lv, left);
MpegAudioL2ToAudio(hdr, raudio, rv, right);
Audio16Merge(left, right, merge);
tout = Audio16CastToBitStream(merge);
BitStreamFileWriteSegment(tout, outf, 0, 4608);
}
BitStreamFree(tout);
len = MpegAudioHdrFind(inbp);
}
MpegAudioL2Free(laudio);
MpegAudioL2Free(raudio);
AudioFree(left);
AudioFree(right);
AudioFree(merge);
MpegAudioSynDataFree(lv);
MpegAudioSynDataFree(rv);
}
void DecodeLayer3 (inbs, inbp, inf, outbs, outbp, outf, hdr)
BitStream *inbs;
BitParser *inbp;
FILE *inf;
BitStream *outbs;
BitParser *outbp;
FILE *outf;
MpegAudioHdr *hdr;
{
MpegAudioSynData *lv, *rv;
Audio *left, *right, *merge;
MpegAudioL3 *audio;
MpegAudioGraData *gra;
BitStream *abs;
BitParser *abp;
BitStream *tout;
int len;
/*
* Initialize various data structure.
* Each layer 1 frames contains 1152 samples from each channel.
*/
lv = MpegAudioSynDataNew();
rv = MpegAudioSynDataNew();
left = Audio16New(1152);
right = Audio16New(1152);
merge = Audio16New(2304);
abs = BitStreamNew(4096);
abp = BitParserNew();
BitParserWrap(abp, abs);
gra = MpegAudioGraDataNew();
audio = MpegAudioL3New();
/*
* Decode the first frame and output it to file.
*/
MpegAudioL3Parse(inbp, abp, hdr, audio);
if (MpegAudioHdrGetMode(hdr) == MPEG_AUDIO_SINGLE_CHANNEL) {
MpegAudioL3MonoToAudio(hdr, audio, lv, gra, left);
tout = Audio16CastToBitStream(left);
BitStreamFileWriteSegment(tout, outf, 0, 2304);
} else {
MpegAudioL3StereoToAudio(hdr, audio, lv, rv, gra, left, right);
Audio16Merge(merge, left, right);
tout = Audio16CastToBitStream(merge);
BitStreamFileWriteSegment(tout, outf, 0, 4608);
}
BitStreamFree(tout);
len = MpegAudioHdrFind(inbp);
/*
* Repeatedly parse a frame header, parse a frame, decode the frame
* and output the samples to file, until we are done with all data.
*/
while (!feof(inf) || len != -1) {
CheckBitStreamUnderflow(inbs, inbp, inf, 4500);
MpegAudioHdrParse(inbp, hdr);
MpegAudioL3Parse(inbp, abp, hdr, audio);
if (MpegAudioHdrGetMode(hdr) == MPEG_AUDIO_SINGLE_CHANNEL) {
MpegAudioL3MonoToAudio(hdr, audio, lv, gra, left);
tout = Audio16CastToBitStream(left);
BitStreamFileWriteSegment(tout, outf, 0, 2304);
} else {
MpegAudioL3StereoToAudio(hdr, audio, lv, rv, gra, left, right);
Audio16Merge(left, right, merge);
tout = Audio16CastToBitStream(merge);
BitStreamFileWriteSegment(tout, outf, 0, 4608);
}
BitStreamFree(tout);
len = MpegAudioHdrFind(inbp);
}
MpegAudioL3Free(audio);
AudioFree(left);
AudioFree(right);
AudioFree(merge);
MpegAudioSynDataFree(lv);
MpegAudioSynDataFree(rv);
MpegAudioGraDataFree(gra);
BitStreamFree(abs);
BitParserFree(abp);
}
int main(int argc, char *argv[])
{
BitParser *inbp, *outbp;
BitStream *inbs, *outbs;
FILE *inf, *outf;
MpegAudioHdr *hdr;
int layer;
/*
* Parse arguments, initialize headers, and open input/output files.
*/
if (argc < 3) {
fprintf(stderr, "usage : %s input output\n", argv[0]);
exit(1);
}
inbp = BitParserNew();
outbp = BitParserNew();
inbs = BitStreamNew(65536);
outbs = BitStreamNew(65536);
inf = fopen(argv[1], "rb");
if (inf == NULL) {
fprintf(stderr, "unable to open file %s for reading", argv[1]);
exit(1);
}
outf = fopen(argv[2], "wb");
if (outf == NULL) {
fprintf(stderr, "unable to open file %s for writing", argv[2]);
exit(1);
}
BitStreamFileRead(inbs, inf, 0);
BitParserWrap(inbp, inbs);
BitParserWrap(outbp, outbs);
/*
* Read the first header to determine which layer this file belongs to.
* Then call the appropiate function the decode the rest of the file.
*/
hdr = MpegAudioHdrNew();
MpegAudioHdrParse(inbp, hdr);
layer = MpegAudioHdrGetLayer(hdr);
if (layer == 1) {
DecodeLayer1(inbs, inbp, inf, outbs, outbp, outf, hdr);
} else if (layer == 2) {
DecodeLayer2(inbs, inbp, inf, outbs, outbp, outf, hdr);
} else {
DecodeLayer3(inbs, inbp, inf, outbs, outbp, outf, hdr);
}
/*
* Clean up here.
*/
fclose(inf);
fclose(outf);
BitStreamFree(inbs);
BitStreamFree(outbs);
BitParserFree(inbp);
BitParserFree(outbp);
MpegAudioHdrFree(hdr);
return 0;
}