readwav.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include "readwav.hpp"
  2. #include "specs.hpp"
  3. #include "macs.hpp"
  4. #include "dprint.hpp"
  5. struct wav_chunk
  6. {
  7. char id[4];
  8. unsigned long size;
  9. char type[4];
  10. } ;
  11. struct wav_tag
  12. {
  13. char id[4];
  14. unsigned long size;
  15. } ;
  16. struct wav_format
  17. {
  18. unsigned short fmt_tag,channels;
  19. unsigned long samplesps,avg_bytesps;
  20. unsigned short align;
  21. } ;
  22. struct pcm_wave
  23. {
  24. wav_format wf;
  25. unsigned short bitsps;
  26. } ;
  27. void read_chunk(wav_chunk &chunk, bFILE *fp)
  28. {
  29. fp->read(&chunk.id,4);
  30. chunk.size=fp->read_long();
  31. fp->read(&chunk.type,4);
  32. }
  33. void read_tag(wav_tag &tag, bFILE *fp)
  34. {
  35. fp->read(&tag.id,4);
  36. tag.size=fp->read_long();
  37. }
  38. void read_wav_format(wav_format &fmt, bFILE *fp)
  39. {
  40. fmt.fmt_tag=fp->read_short();
  41. fmt.channels=fp->read_short();
  42. fmt.samplesps=fp->read_long();
  43. fmt.avg_bytesps=fp->read_long();
  44. fmt.align=fp->read_short();
  45. }
  46. void read_pcm(pcm_wave &pcm, bFILE *fp)
  47. {
  48. read_wav_format(pcm.wf,fp);
  49. pcm.bitsps=fp->read_short();
  50. }
  51. void write_wav(char *filename, long sample_rate, long data_size, unsigned char *data)
  52. {
  53. wav_chunk chunk;
  54. wav_tag tag;
  55. pcm_wave pcm;
  56. bFILE *fp=open_file(filename,"wb");
  57. if (fp->open_failure())
  58. {
  59. printf("Unable to open %s for writing\n");
  60. delete fp;
  61. exit(1);
  62. }
  63. /*************** Write the chunk ***************************/
  64. fp->write("RIFF",4);
  65. fp->write_long(data_size+36);
  66. fp->write("WAVE",4);
  67. /************** Write the tag *******************************/
  68. fp->write("fmt ",4);
  69. fp->write_long(16);
  70. /************** Write PCM ***********************************/
  71. fp->write_short(1); // format_tag
  72. fp->write_short(1); // mono recording
  73. fp->write_long(sample_rate);
  74. fp->write_long(sample_rate); // average bytes per sec
  75. fp->write_short(1); // allignment? Don't know what this does?
  76. fp->write_short(8); // 8 bits per sample
  77. /************* Write data tag ******************************/
  78. fp->write("data",4);
  79. fp->write_long(data_size);
  80. /************ Now write sample data ************************/
  81. fp->write(data,data_size);
  82. delete fp;
  83. }
  84. unsigned char *read_wav(char *filename, long &sample_rate, long &data_size)
  85. {
  86. unsigned char *data;
  87. wav_chunk chunk;
  88. wav_tag tag;
  89. pcm_wave pcm;
  90. bFILE *fp=open_file(filename,"rb");
  91. if (fp->open_failure())
  92. { delete fp; return NULL; }
  93. read_chunk(chunk,fp);
  94. if (memcmp(chunk.type,"WAVE",4)!=0)
  95. {
  96. printf("Bad WAV file (chunk) %s\n",filename);
  97. delete fp;
  98. return NULL;
  99. }
  100. read_tag(tag,fp);
  101. if (memcmp(tag.id,"fmt ",4)!=0)
  102. {
  103. printf( "fmt tag missing, bad file (%s)\n",filename);
  104. delete fp;
  105. return NULL;
  106. }
  107. read_pcm(pcm,fp);
  108. fp->seek(tag.size-16,SEEK_CUR); // seek to offset of sample
  109. read_tag(tag,fp);
  110. if (memcmp(tag.id,"data",4)!=0)
  111. {
  112. printf("Bad Wav file (tag), %s\n",filename);
  113. delete fp;
  114. return NULL;
  115. }
  116. data_size=tag.size;
  117. data=(unsigned char *)jmalloc(tag.size,"WAV data");
  118. ERROR(data,"Malloc error");
  119. sample_rate=pcm.wf.samplesps;
  120. ERROR(fp->read(data,tag.size)==tag.size,"Premature end of file");
  121. ERROR(pcm.bitsps==8,"Only 8-bit samples supported");
  122. ERROR(pcm.wf.channels==1,"Only mono samples supported");
  123. ERROR(pcm.wf.align==1,"Bad block allignment");
  124. delete fp;
  125. return data;
  126. }