/*------------------------------------------------------------------------ * * 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; }