home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 4
/
AACD04.ISO
/
AACD
/
Sound
/
MPdecode
/
mpdecode.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-10-31
|
9KB
|
414 lines
#define TEMPLATE "Names/M,OutDir/K"
#define BUFFERS 64
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/mpega.h>
#include <exec/memory.h>
char Version[]="\0$VER: mpdecode 1.0 (30.10.99) by Thomas Wenzel\0";
struct Library *MPEGABase;
MPEGA_CTRL mctrl;
MPEGA_STREAM *mstream;
struct RDArgs *rdargs;
struct AnchorPath *APath;
char *CurrentName;
ULONG NameCount;
ULONG Signals;
WORD *Buffer[MPEGA_MAX_CHANNELS];
WORD *OutBuffer;
char OutDir[1024];
struct { /* Args structure */
char **Names;
char *OutDir;
} Args = {
NULL,
NULL
};
struct {
ULONG FORMid;
ULONG FORMsize;
ULONG AIFFid;
ULONG FVERid;
ULONG FVERsize;
ULONG FVERtime;
ULONG COMMid;
ULONG COMMsize;
UWORD nTracks;
ULONG nFrames;
UWORD bpSmpl;
char freq[10];
ULONG compType;
char compressionName[(sizeof("not compressed")+1)&(~1)];
ULONG SSNDid;
ULONG SSNDsize;
ULONG offset;
ULONG blockSize;
} AIFFheader = {
0x464F524D, // FORM
NULL,
0x41494643, // AIFC
0x46564552, // FVER
4,
0xA2805140, // file format version #1
0x434F4D4D, // COMM
38,
2,
0,
16,
0,0,0,0,0,0,0,0,0,0,
0x4E4F4E45, // NONE
sizeof("not compressed")-1,'n','o','t',' ','c','o','m','p','r','e','s','s','e','d',0,
0x53534E44,
0,
0,
0
};
BOOL Init(void);
void Free(void);
void Decode(char *Name);
void ConvertToIeeeExtended(double, char *);
int main(int argc, char **argv) {
char c;
printf("\n");
printf("mpdecode 1.0 by Thomas Wenzel\n");
printf("-----------------------------\n");
printf("This program decodes multiple MPEG audio files to AIFF-C.\n");
printf("Freeware. Provided 'as is'. For non-commercial use only.\n");
printf("\n");
if(!Init()) {
Free();
return(10);
}
if((rdargs = ReadArgs(TEMPLATE, (LONG *)&Args, NULL)) == NULL) {
PrintFault(IoErr(), "mpdecode");
Free();
return(10);
}
if(!Args.Names) {
printf("Usage: mpdecode %s\n", TEMPLATE);
Free();
return(5);
}
if(Args.OutDir) {
strcpy(OutDir, Args.OutDir);
c=OutDir[strlen(OutDir)-1];
if((c != ':') && (c != '/')) strcat(OutDir, "/");
}
else {
OutDir[0]=0;
}
NameCount=0;
while(Args.Names[NameCount]!=NULL) {
CurrentName=Args.Names[NameCount];
if(MatchFirst(CurrentName,APath)==0) {
do {
Signals=CheckSignal(SIGBREAKF_CTRL_C);
if(Signals) break;
Decode(APath->ap_Buf);
} while (MatchNext(APath)==0);
MatchEnd(APath);
if(Signals) break;
}
NameCount++;
}
if(Signals) printf("mpdecode: BREAK\n");
Free();
return(0);
}
BOOL Init(void) {
ULONG i;
MPEGABase=OpenLibrary("mpega.library", 2);
if(!MPEGABase) {
printf("Can't open mpega.library v2\n");
return(FALSE);
}
APath=AllocVec(sizeof(*APath)+256, MEMF_PUBLIC|MEMF_CLEAR);
if(!APath) {
printf("Out of memory!\n");
return(FALSE);
}
APath->ap_Strlen=255;
for(i=0; i<MPEGA_MAX_CHANNELS; i++) {
Buffer[i]=AllocVec(BUFFERS*MPEGA_PCM_SIZE*sizeof(WORD), MEMF_PUBLIC|MEMF_CLEAR);
if(!Buffer[i]) {
printf("Out of memory!\n");
return(FALSE);
}
}
OutBuffer=AllocVec(BUFFERS*MPEGA_PCM_SIZE*sizeof(WORD)*2, MEMF_PUBLIC|MEMF_CLEAR);
if(!OutBuffer) {
printf("Out of memory!\n");
return(FALSE);
}
mctrl.bs_access = NULL;
mctrl.layer_1_2.force_mono = 0;
mctrl.layer_1_2.mono.freq_div = 1;
mctrl.layer_1_2.mono.quality = 2;
mctrl.layer_1_2.mono.freq_max = 48000;
mctrl.layer_1_2.stereo.freq_div = 1;
mctrl.layer_1_2.stereo.quality = 2;
mctrl.layer_1_2.stereo.freq_max = 48000;
mctrl.layer_3.force_mono = 0;
mctrl.layer_3.mono.freq_div = 1;
mctrl.layer_3.mono.quality = 2;
mctrl.layer_3.mono.freq_max = 48000;
mctrl.layer_3.stereo.freq_div = 1;
mctrl.layer_3.stereo.quality = 2;
mctrl.layer_3.stereo.freq_max = 48000;
mctrl.check_mpeg = 1;
mctrl.stream_buffer_size = 0;
}
void Free(void) {
ULONG i;
for(i=0; i<MPEGA_MAX_CHANNELS; i++) {
if(Buffer[i]) FreeVec(Buffer[i]);
}
if(OutBuffer) FreeVec(OutBuffer);
if(rdargs) FreeArgs(rdargs);
if(APath) FreeVec(APath);
if(MPEGABase) CloseLibrary(MPEGABase);
}
void Decode(char *Name) {
ULONG i,j,ptr;
FILE *OutFile;
char OutFileName[1024];
ULONG BadFrames;
LONG Count;
ULONG SamplesInFile;
ULONG SamplesInBuf;
ULONG BytesWritten;
ULONG Length, Time;
BOOL WriteError;
BOOL eof;
WriteError=FALSE;
eof=FALSE;
if(OutDir[0]) {
sprintf(OutFileName, "%s%s.aiff", OutDir, FilePart(Name));
}
else {
sprintf(OutFileName, "%s.aiff", Name);
}
printf("\nFilename: %s -> %s\n", Name, OutFileName);
mstream=MPEGA_open(Name, &mctrl);
if(!mstream) {
printf("Can't open input file!\n");
return;
}
OutFile=fopen(OutFileName, "wb");
if(!OutFile) {
printf("Can't open output file!\n");
MPEGA_close(mstream);
return;
}
if(fwrite(&AIFFheader, sizeof(AIFFheader), 1, OutFile) != 1) WriteError=TRUE;
Length=mstream->ms_duration/1000;
SamplesInFile=0;
BadFrames=0;
while(!eof) {
if(MPEGA_time(mstream, &Time)==0) {
printf("Decoding: %ds/%ds (%d%%)", Time/1000, Length, Time/Length/10);
if(BadFrames) printf(" [%d bad frames]", BadFrames);
printf("\r");
}
flushall();
ptr=0;
SamplesInBuf=0;
for(i=0; i<BUFFERS; i++) {
Signals=CheckSignal(SIGBREAKF_CTRL_C);
if(Signals || WriteError) break;
Count=MPEGA_decode_frame(mstream, Buffer);
if(Count==MPEGA_ERR_BADFRAME) BadFrames++;
if(Count < 0) {
if(Count==MPEGA_ERR_EOF) {
eof=TRUE;
}
else {
Count=0;
}
}
if(Count>BUFFERS*MPEGA_PCM_SIZE) Count=BUFFERS*MPEGA_PCM_SIZE;
if(Count>0) {
switch(mstream->channels) {
case 1:
for(j=0; j<Count; j++) {
OutBuffer[ptr++] = Buffer[0][j];
}
break;
case 2:
for(j=0; j<Count; j++) {
OutBuffer[ptr++] = Buffer[0][j];
OutBuffer[ptr++] = Buffer[1][j];
}
break;
}
}
SamplesInBuf += Count;
}
if(Signals || WriteError) break;
if(SamplesInBuf) {
if(fwrite(OutBuffer, SamplesInBuf, 2*mstream->channels, OutFile) != 2*mstream->channels) WriteError=TRUE;
SamplesInFile += SamplesInBuf;
}
}
BytesWritten=SamplesInFile*2*mstream->channels;
AIFFheader.bpSmpl = 16;
AIFFheader.nFrames = SamplesInFile;
AIFFheader.SSNDsize = BytesWritten +4+4; // +4+4: offset and blockSize
ConvertToIeeeExtended((double)mstream->frequency, AIFFheader.freq);
AIFFheader.nTracks = mstream->channels;
AIFFheader.FORMsize = BytesWritten+70 +4+4; // +4+4: offset and blockSize
fseek(OutFile, 0, SEEK_SET);
fwrite(&AIFFheader, sizeof(AIFFheader), 1, OutFile);
MPEGA_close(mstream);
fclose(OutFile);
if(WriteError) printf("\nCan't write to output file!\n");
if(Signals || WriteError) printf("\n");
else printf("Decoding: %ds/%ds (%d%%)\n", Length, Length, 100);
}
/*
* C O N V E R T T O I E E E E X T E N D E D
*/
/* Copyright (C) 1988-1991 Apple Computer, Inc.
* All rights reserved.
*
* Machine-independent I/O routines for IEEE floating-point numbers.
*
* NaN's and infinities are converted to HUGE_VAL or HUGE, which
* happens to be infinity on IEEE machines. Unfortunately, it is
* impossible to preserve NaN's in a machine-independent way.
* Infinities are, however, preserved on IEEE machines.
*
* These routines have been tested on the following machines:
* Apple Macintosh, MPW 3.1 C compiler
* Apple Macintosh, THINK C compiler
* Silicon Graphics IRIS, MIPS compiler
* Cray X/MP and Y/MP
* Digital Equipment VAX
*
*
* Implemented by Malcolm Slaney and Ken Turkowski.
*
* Malcolm Slaney contributions during 1988-1990 include big- and little-
* endian file I/O, conversion to and from Motorola's extended 80-bit
* floating-point format, and conversions to and from IEEE single-
* precision floating-point format.
*
* In 1991, Ken Turkowski implemented the conversions to and from
* IEEE double-precision format, added more precision to the extended
* conversions, and accommodated conversions involving +/- infinity,
* NaN's, and denormalized numbers.
*/
# define FloatToUnsigned(f) ((unsigned long)(((long)(f - 2147483648.0)) + 2147483647L) + 1)
void ConvertToIeeeExtended(double num, char *bytes) {
int sign;
int expon;
double fMant, fsMant;
ULONG hiMant, loMant;
if (num < 0) {
sign = 0x8000;
num *= -1;
}
else sign = 0;
if (num == 0) {
expon = 0; hiMant = 0; loMant = 0;
}
else {
fMant = frexp(num, &expon);
if ((expon > 16384) || !(fMant < 1)) { /* Infinity or NaN */
expon = sign|0x7FFF; hiMant = 0; loMant = 0; /* infinity */
}
else { /* Finite */
expon += 16382;
if (expon < 0) { /* denormalized */
fMant = ldexp(fMant, expon);
expon = 0;
}
expon |= sign;
fMant = ldexp(fMant, 32);
fsMant = floor(fMant);
hiMant = FloatToUnsigned(fsMant);
fMant = ldexp(fMant - fsMant, 32);
fsMant = floor(fMant);
loMant = FloatToUnsigned(fsMant);
}
}
bytes[0] = expon >> 8;
bytes[1] = expon;
bytes[2] = hiMant >> 24;
bytes[3] = hiMant >> 16;
bytes[4] = hiMant >> 8;
bytes[5] = hiMant;
bytes[6] = loMant >> 24;
bytes[7] = loMant >> 16;
bytes[8] = loMant >> 8;
bytes[9] = loMant;
}