// GC DVD ADPCM decoding algorithm // NOTE: the ADPCM format used by the dvd drive is *NOT* the same as the ADPCM format used by the DSP // they are similiar but the dvd adpcm format requires less multiplies // previous public decoder by Shinji Chiba is innacurate // -Crazynation #include int predL1,predL2,predR1,predR2; int new_pred; init_predictors() { predL1=0; predL2=0; predR1=0; predR2=0; } int decode(int predictor1,int predictor2,int nibble,int index) { int i,j,k; short scalex,scaley; int data1,data2; switch(index>>4) { case 0: scalex=0; scaley=0; break; case 1: scalex=0x3C; scaley=0; break; case 2: scalex=0x73; scaley=0xFFCC; break; case 3: scalex=0x62; scaley=0xFFC9; break; default: break; } i=predictor1*scalex; j=predictor2*scaley; i=i+j+0x20; i=i>>6; if(i<(int)0xFFE00000) i=0xFFE00000; else if(i>0x1FFFFF) i=0x1FFFFF; data1=i; j=(nibble&0xF)<<12; j=(short)j>>(index&0xF); i=j<<6; i=i+data1; data2=i; new_pred=data2; j=data2>>6; if(j<(int)0xFFFF8000) j=0x8000; else if(j>0x7FFF) j=0x7FFF; return j; } char wav_header[]={0x52,0x49,0x46,0x46,0x26,0x40,0x21,0x00,0x57,0x41,0x56,0x45,0x66,0x6D,0x74,0x20, 0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x80,0xBB,0x00,0x00,0x00,0xEE,0x02,0x00, 0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61,0x00,0x40,0x21,0x00}; int main(int argc, char *argv[]) { int i,j,k; int count,length,offset; int nibble_high,nibble_low; FILE *fin,*fout; unsigned char buffer[32]; short wav[128]; if(argc<3) { printf("decode \n"); exit(1); } fin=fopen(argv[1],"rb"); if(fin==0) { printf("cant open input file %s\n",argv[1]); exit(1); } fout=fopen(argv[2],"wb"); if(fout==0) { printf("cant open output file %s\n",argv[2]); exit(1); } fseek(fin,0,SEEK_END); length=ftell(fin); fseek(fin,0,SEEK_SET); init_predictors(); offset=0; fwrite(wav_header,44,1,fout); //----------------------------------------------------------------------------- decode: i=fread(buffer,32,1,fin); if(i==0) exit(1); if(buffer[0]!=buffer[2]) { printf("invalid ADPCM file\n"); exit(1); } if(buffer[1]!=buffer[3]) { printf("invalid ADPCM file\n"); exit(1); } count=0; do{ nibble_high=buffer[count+4]>>4; nibble_low=buffer[count+4]&0xF; k=decode(predL1,predL2,nibble_low,buffer[0]); wav[count*2]=k; predL2=predL1; predL1=new_pred; k=decode(predR1,predR2,nibble_high,buffer[1]); wav[(count*2)+1]=k; predR2=predR1; predR1=new_pred; count++; }while(count<28); fwrite(wav,28*4,1,fout); offset+=32; if(offset