home *** CD-ROM | disk | FTP | other *** search
/ Computer Installation Guide - Dragon Clan Series / CD2.iso / Audio / CPMPXPL2 / MP3WAV.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-01  |  6.4 KB  |  273 lines

  1. // MP3 to WAV converter (c) '97 N. Beisert (nbeisert@physik.tu-muenchen.de)
  2. // you are free to do with this stuff whatever you like. it's freeware.
  3.  
  4. #include <conio.h>
  5. #include <dos.h>
  6. #include <direct.h>
  7. #include <string.h>
  8. #include <io.h>
  9. #include <fcntl.h>
  10. #include <sys/stat.h>
  11.  
  12. const int buflen=16384;
  13. static char buf[buflen];
  14.  
  15. struct
  16. {
  17.   char riff[4];
  18.   long rifflen;
  19.   char wave[4];
  20.   char fmt[4];
  21.   long fmtlen;
  22.   short format;
  23.   short chan;
  24.   long freq;
  25.   long rate;
  26.   short align;
  27.   short bits;
  28.   short extra;
  29.   short dunno1;
  30.   short dunno2;
  31.   short dunno3;
  32.   short blklen;
  33.   short dunno4;
  34.   short dunno5;
  35.   char data[4];
  36.   long datalen;
  37. } wavehdr;
  38.  
  39. int getheader(unsigned long hdr, int &layer, int &ver, int &freq, int &stereo, int &rate)
  40. {
  41.   if ((hdr&0xF0FF)!=0xF0FF)
  42.     return 0;
  43.   ver=(hdr>>11)&1;
  44.   layer=4-((hdr>>9)&3);
  45.   if (layer==4)
  46.     return 0;
  47.   int rateidx=(hdr>>20)&15;
  48.   int frqidx=(hdr>>18)&3;
  49.   stereo="\x02\x02\x02\x01"[(hdr>>30)&3];
  50.   switch (frqidx)
  51.   {
  52.   case 0: freq=44100; break;
  53.   case 1: freq=48000; break;
  54.   case 2: freq=32000; break;
  55.   default: return 0;
  56.   }
  57.   if (ver)
  58.     switch (layer)
  59.     {
  60.     case 1: rate="\x00\x04\x08\x0C\x10\x14\x18\x1C\x20\x24\x28\x2C\x30\x34\x38\x00"[rateidx]*1000; break;
  61.     case 2: rate="\x00\x04\x06\x07\x08\x0A\x0C\x0E\x10\x14\x18\x1C\x20\x28\x30\x00"[rateidx]*1000; break;
  62.     case 3: rate="\x00\x04\x05\x06\x07\x08\x0A\x0C\x0E\x10\x14\x18\x1C\x20\x28\x00"[rateidx]*1000; break;
  63.     default: return 0;
  64.     }
  65.   else
  66.     switch (layer)
  67.     {
  68.     case 1: rate="\x00\x04\x06\x07\x08\x0A\x0C\x0E\x10\x12\x14\x16\x18\x1C\x20\x00"[rateidx]*1000; break;
  69.     case 2: rate="\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0A\x0C\x0E\x10\x12\x14\x00"[rateidx]*1000; break;
  70.     case 3: rate="\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0A\x0C\x0E\x10\x12\x14\x00"[rateidx]*1000; break;
  71.     default: return 0;
  72.     }
  73.  
  74.   if (!ver)
  75.     freq>>=1;
  76.   if (!rate)
  77.     return 0;
  78.   return 1;
  79. }
  80.  
  81. int conv(const char *name, int kill, int ext, int excl)
  82. {
  83.   static char outname[300];
  84.  
  85.   strcpy(outname, name);
  86.   if (!ext&&!stricmp(outname+strlen(outname)-4, ".mp3"))
  87.     outname[strlen(outname)-4]=0;
  88.   strcat(outname, ".wav");
  89.  
  90.   char tag[128];
  91.   int fi=open(name, O_RDONLY|O_BINARY);
  92.   if (fi<0)
  93.     return 1;
  94.   long len=filelength(fi);
  95.   lseek(fi, -128, SEEK_END);
  96.   *tag=0;
  97.   read(fi, tag, 128);
  98.   if (!memcmp(tag, "TAG", 3))
  99.     len-=128;
  100.   lseek(fi, 0, SEEK_SET);
  101.   unsigned long hdr;
  102.   read(fi, &hdr, 4);
  103.   lseek(fi, 0, SEEK_SET);
  104.  
  105.   int chan=2;
  106.   int layer,freq,rate,ver;
  107.   if (!getheader(hdr, layer, ver, freq, chan, rate))
  108.     return 1;
  109.   if (layer!=3)
  110.     return 1;
  111.   int blklen=(288<<ver)*chan*rate/freq;
  112.  
  113.   memcpy(wavehdr.riff, "RIFF", 4);
  114.   wavehdr.rifflen=sizeof(wavehdr)-8+(memcmp(tag, "TAG", 3)?0:136)+len;
  115.   memcpy(wavehdr.wave, "WAVE", 4);
  116.   memcpy(wavehdr.fmt, "fmt ", 4);
  117.   wavehdr.fmtlen=30;
  118.   wavehdr.format=0x55;
  119.   wavehdr.bits=0;
  120.   wavehdr.chan=chan;
  121.   wavehdr.freq=freq;
  122.   wavehdr.rate=rate;
  123.   wavehdr.align=(layer==1)?4:1;
  124.   wavehdr.extra=12;
  125.   wavehdr.dunno1=1;
  126.   wavehdr.dunno2=2;
  127.   wavehdr.dunno3=0;
  128.   wavehdr.blklen=blklen;
  129.   wavehdr.dunno4=1;
  130.   wavehdr.dunno5=0x571;
  131.   memcpy(wavehdr.data, "data", 4);
  132.   wavehdr.datalen=len;
  133.  
  134.   int fo=open(outname, O_WRONLY|O_BINARY|O_TRUNC|O_CREAT|(excl?O_EXCL:0), S_IREAD|S_IWRITE);
  135.   if (fo<0)
  136.     return 0;
  137.   write(fo, &wavehdr, sizeof(wavehdr));
  138.   cputs(name);
  139.  
  140.   long pos=0;
  141.   while (1)
  142.   {
  143.     long l=len-pos;
  144.     if (l>buflen)
  145.       l=buflen;
  146.     if (!l)
  147.       break;
  148.     read(fi, buf, l);
  149.     write(fo, buf, l);
  150.     pos+=l;
  151.   }
  152.   if (!memcmp(tag, "TAG", 3))
  153.   {
  154.     write(fo, "$TAG", 4);
  155.     write(fo, "\x80\0\0\0", 4);
  156.     write(fo, tag, 128);
  157.   }
  158.   len=filelength(fo)-8;
  159.   lseek(fo, 4, SEEK_SET);
  160.   write(fo, &len, 4);
  161.   close(fi);
  162.   close(fo);
  163.   if (kill)
  164.     unlink(name);
  165.   cputs("\n");
  166.   return 0;
  167. }
  168.  
  169. void convdir(const char *base, const char *sub, const char *mask, int recurse, int kill, int ext, int excl)
  170. {
  171.   char *pathbuf=new char [400];
  172.   strcpy(pathbuf, base);
  173.   strcat(pathbuf, sub);
  174.   strcat(pathbuf, mask);
  175.  
  176.   const int buflen=4096;
  177.   static char buffer[buflen];
  178.   find_t fnd;
  179.   int found;
  180.   for (found=!_dos_findfirst(pathbuf, _A_NORMAL, &fnd); found; found=!_dos_findnext(&fnd))
  181.   {
  182.     strcpy(pathbuf, base);
  183.     strcat(pathbuf, sub);
  184.     strcat(pathbuf, fnd.name);
  185.     conv(pathbuf, kill, ext, excl);
  186.   }
  187.   if (!recurse)
  188.     return;
  189.   strcpy(pathbuf, base);
  190.   strcat(pathbuf, sub);
  191.   strcat(pathbuf, "*");
  192.   for (found=!_dos_findfirst(pathbuf, _A_SUBDIR, &fnd); found; found=!_dos_findnext(&fnd))
  193.   {
  194.     if (!(fnd.attrib&_A_SUBDIR)||!strcmp(fnd.name, ".")||!strcmp(fnd.name, ".."))
  195.       continue;
  196.     strcpy(pathbuf, sub);
  197.     strcat(pathbuf, fnd.name);
  198.     strcat(pathbuf, "\\");
  199.  
  200.     convdir(base, pathbuf, mask, 1, kill, ext, excl);
  201.   }
  202.   delete pathbuf;
  203. }
  204.  
  205. int isdir(const char *x)
  206. {
  207.   find_t fnd;
  208.   if (strchr(x, '?')||strchr(x, '*')||_dos_findfirst(x, _A_SUBDIR, &fnd))
  209.     return 0;
  210.   return (fnd.attrib&_A_SUBDIR)?1:0;
  211. }
  212.  
  213.  
  214. int main(int argn, char **argv)
  215. {
  216.   cputs("mp3 to mp3-wav converter (c) '97 Niklas Beisert\n\n");
  217.  
  218.   int excl=1;
  219.   int help=1;
  220.   int kill=0;
  221.   int recurse=0;
  222.   int ext=0;
  223.   int i;
  224.   for (i=1; i<argn; i++)
  225.   {
  226.     if (!stricmp(argv[i], "/k"))
  227.       kill=1;
  228.     if (!stricmp(argv[i], "/r"))
  229.       recurse=1;
  230.     if (!stricmp(argv[i], "/e"))
  231.       ext=1;
  232.     if (!stricmp(argv[i], "/o"))
  233.       excl=0;
  234.   }
  235.   for (i=1; i<argn; i++)
  236.   {
  237.     if (argv[i][0]=='/')
  238.       continue;
  239.  
  240.     char path[300];
  241.     strcpy(path, argv[i]);
  242.     if (path[0]&&(path[1]==':')&&(path[2]!='\\'))
  243.     {
  244.       memmove(path+4, path+2, strlen(path)-1);
  245.       path[2]='.';
  246.       path[3]='\\';
  247.     }
  248.     char mask[300];
  249.     if (isdir(path))
  250.       strcat(path, "\\");
  251.     char *p=strrchr(path, '\\')?(strrchr(path, '\\')+1):path;
  252.     strcpy(mask, p);
  253.     *p=0;
  254.     if (!*path)
  255.       strcpy(path, ".\\");
  256.     if (!*mask)
  257.       strcpy(mask, "*");
  258.  
  259.     convdir(path, "", mask, recurse, kill, ext, excl);
  260.     help=0;
  261.   }
  262.  
  263.   if (help)
  264.   {
  265.     cputs("syntax: mp3wav [/r] [/k] [/o] [/e] files\n");
  266.     cputs("  /r: recurse subdirectories\n");
  267.     cputs("  /o: overwrite existing files\n");
  268.     cputs("  /k: kill originals\n");
  269.     cputs("  /e: always add .wav extension (otherwise replace .mp3 by .wav)\n");
  270.   }
  271.   return 0;
  272. }
  273.