fork download
  1. // Convert a set of WAV audio files to C data arrays for the Teensy3 Audio Library
  2. // Copyright 2014, Paul Stoffregen (paul@pjrc.com)
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21.  
  22. // compile with: gcc -O2 -Wall -o wav2sketch wav2sketch.c
  23. // i686-w64-mingw32-gcc -s -O2 -Wall wav2sketch.c -o wav2sketch.exe
  24.  
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <stdint.h>
  28. #include <stdarg.h>
  29. #include <string.h>
  30. #include <ctype.h>
  31. #include <sys/types.h>
  32. #include <sys/stat.h>
  33. #include <dirent.h>
  34.  
  35. uint8_t ulaw_encode(int16_t audio);
  36. void print_byte(FILE *out, uint8_t b);
  37. void filename2samplename(void);
  38. uint32_t padding(uint32_t length, uint32_t block);
  39. uint8_t read_uint8(FILE *in);
  40. int16_t read_int16(FILE *in);
  41. uint32_t read_uint32(FILE *in);
  42. void die(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
  43.  
  44. // WAV file format:
  45. // http://w...content-available-to-author-only...l.ca/Documents/AudioFormats/WAVE/WAVE.html
  46.  
  47. const char *filename="";
  48. char samplename[64];
  49. unsigned int bcount, wcount;
  50. unsigned int total_length=0;
  51. int pcm_mode=0;
  52.  
  53. void wav2c(FILE *in, FILE *out, FILE *outh)
  54. {
  55. uint32_t header[4];
  56. int16_t format, channels, bits;
  57. uint32_t rate;
  58. uint32_t i, length, padlength=0, arraylen;
  59. uint32_t chunkSize;
  60. int32_t audio=0;
  61.  
  62. // read the WAV file's header
  63. for (i=0; i < 4; i++) {
  64. header[i] = read_uint32(in);
  65. }
  66. while (header[3] != 0x20746D66) {
  67. // skip past unknown sections until "fmt "
  68. chunkSize = read_uint32(in);
  69. for (i=0; i < chunkSize; i++) {
  70. read_uint8(in);
  71. }
  72. header[3] = read_uint32(in);
  73. }
  74. chunkSize = read_uint32(in);
  75.  
  76. // read the audio format parameters
  77. format = read_int16(in);
  78. channels = read_int16(in);
  79. rate = read_uint32(in);
  80. read_uint32(in); // ignore byterate
  81. read_int16(in); // ignore blockalign
  82. bits = read_int16(in);
  83. //printf("format: %d, channels: %d, rate: %d, bits %d\n", format, channels, rate, bits);
  84. if (format != 1)
  85. die("file %s is compressed, only uncompressed supported", filename);
  86. if (rate != 44100 && rate != 22050 && rate != 11025 /*&& rate != 8000*/ )
  87. die("sample rate %d in %s is unsupported\n"
  88. "Only 44100, 22050, 11025 work", rate, filename);
  89. if (channels != 1 && channels != 2)
  90. die("file %s has %d channels, but only 1 & 2 are supported", filename, channels);
  91. if (bits != 16)
  92. die("file %s has %d bit format, but only 16 is supported", filename, bits);
  93.  
  94. // skip past any extra data on the WAVE header (hopefully it doesn't matter?)
  95. for (chunkSize -= 16; chunkSize > 0; chunkSize--) {
  96. read_uint8(in);
  97. }
  98.  
  99. // read the data header, skip non-audio data
  100. while (1) {
  101. header[0] = read_uint32(in);
  102. length = read_uint32(in);
  103. if (header[0] == 0x61746164) break; // beginning of actual audio data
  104. // skip over non-audio data
  105. for (i=0; i < length; i++) {
  106. read_uint8(in);
  107. }
  108. }
  109.  
  110. // the length must be a multiple of the data size
  111. if (channels == 2) {
  112. if (length % 4) die("file %s data length is not a multiple of 4", filename);
  113. length = length / 4;
  114. }
  115. if (channels == 1) {
  116. if (length % 1) die("file %s data length is not a multiple of 2", filename);
  117. length = length / 2;
  118. }
  119. if (length > 0xFFFFFF) die("file %s data length is too long", filename);
  120. bcount = 0;
  121.  
  122. // AudioPlayMemory requires padding to 2.9 ms boundary (128 samples @ 44100)
  123. if (rate == 44100) {
  124. padlength = padding(length, 128);
  125. format = 1;
  126. } else if (rate == 22050) {
  127. padlength = padding(length, 64);
  128. format = 2;
  129. } else if (rate == 11025) {
  130. padlength = padding(length, 32);
  131. format = 3;
  132. }
  133. if (pcm_mode) {
  134. arraylen = ((length + padlength) * 2 + 3) / 4 + 1;
  135. format |= 0x80;
  136. } else {
  137. arraylen = (length + padlength + 3) / 4 + 1;
  138. }
  139. total_length += arraylen;
  140.  
  141. // output a minimal header, just the length, #bits and sample rate
  142. fprintf(outh, "extern const unsigned int AudioSample%s[%d];\n", samplename, arraylen);
  143. fprintf(out, "// Converted from %s, using %d Hz, %s encoding\n", filename, rate,
  144. (pcm_mode ? "16 bit PCM" : "u-law"));
  145. fprintf(out, "PROGMEM const unsigned int AudioSample%s[%d] = {\n", samplename, arraylen);
  146. fprintf(out, "0x%08X,", length | (format << 24));
  147. wcount = 1;
  148.  
  149. // finally, read the audio data
  150. while (length > 0) {
  151. if (channels == 1) {
  152. audio = read_int16(in);
  153. } else {
  154. audio = read_int16(in);
  155. audio += read_int16(in);
  156. audio /= 2;
  157. }
  158. if (pcm_mode) {
  159. print_byte(out, audio);
  160. print_byte(out, audio >> 8);
  161. } else {
  162. print_byte(out, ulaw_encode(audio));
  163. }
  164. length--;
  165. }
  166. while (padlength > 0) {
  167. print_byte(out, 0);
  168. padlength--;
  169. }
  170. while (bcount > 0) {
  171. print_byte(out, 0);
  172. }
  173. if (wcount > 0) fprintf(out, "\n");
  174. fprintf(out, "};\n");
  175. }
  176.  
  177.  
  178. uint8_t ulaw_encode(int16_t audio)
  179. {
  180. uint32_t mag, neg;
  181.  
  182. // http://e...content-available-to-author-only...a.org/wiki/G.711
  183. if (audio >= 0) {
  184. mag = audio;
  185. neg = 0;
  186. } else {
  187. mag = audio * -1;
  188. neg = 0x80;
  189. }
  190. mag += 128;
  191. if (mag > 0x7FFF) mag = 0x7FFF;
  192. if (mag >= 0x4000) return neg | 0x70 | ((mag >> 10) & 0x0F); // 01wx yz00 0000 0000
  193. if (mag >= 0x2000) return neg | 0x60 | ((mag >> 9) & 0x0F); // 001w xyz0 0000 0000
  194. if (mag >= 0x1000) return neg | 0x50 | ((mag >> 8) & 0x0F); // 0001 wxyz 0000 0000
  195. if (mag >= 0x0800) return neg | 0x40 | ((mag >> 7) & 0x0F); // 0000 1wxy z000 0000
  196. if (mag >= 0x0400) return neg | 0x30 | ((mag >> 6) & 0x0F); // 0000 01wx yz00 0000
  197. if (mag >= 0x0200) return neg | 0x20 | ((mag >> 5) & 0x0F); // 0000 001w xyz0 0000
  198. if (mag >= 0x0100) return neg | 0x10 | ((mag >> 4) & 0x0F); // 0000 0001 wxyz 0000
  199. else return neg | 0x00 | ((mag >> 3) & 0x0F); // 0000 0000 1wxy z000
  200. }
  201.  
  202.  
  203.  
  204. // compute the extra padding needed
  205. uint32_t padding(uint32_t length, uint32_t block)
  206. {
  207. uint32_t extra;
  208.  
  209. extra = length % block;
  210. if (extra == 0) return 0;
  211. return block - extra;
  212. }
  213.  
  214. // pack the output bytes into 32 bit words, lsb first, and
  215. // format the data nicely with commas and newlines
  216. void print_byte(FILE *out, uint8_t b)
  217. {
  218. static uint32_t buf32=0;
  219.  
  220. buf32 |= (b << (8 * bcount++));
  221. if (bcount >= 4) {
  222. fprintf(out, "0x%08X,", buf32);
  223. buf32 = 0;
  224. bcount = 0;
  225. if (++wcount >= 8) {
  226. fprintf(out, "\n");
  227. wcount = 0;
  228. }
  229. }
  230. }
  231.  
  232. // convert the WAV filename into a C-compatible name
  233. void filename2samplename(void)
  234. {
  235. int len, i, n;
  236. char c;
  237.  
  238. len = strlen(filename) - 4;
  239. if (len >= sizeof(samplename)-1) len = sizeof(samplename)-1;
  240. for (i=0, n=0; n < len; i++) {
  241. c = filename[i];
  242. if (isalpha(c) || c == '_' || (isdigit(c) && n > 0)) {
  243. samplename[n] = (n == 0) ? toupper(c) : tolower(c);
  244. n++;
  245. }
  246. }
  247. samplename[n] = 0;
  248. }
  249.  
  250.  
  251. const char *title = "// Audio data converted from WAV file by wav2sketch\n\n";
  252.  
  253. int main(int argc, char **argv)
  254. {
  255. DIR *dir;
  256. struct dirent *f;
  257. struct stat s;
  258. FILE *fp, *outc=NULL, *outh=NULL;
  259. char buf[128];
  260. int i, len;
  261.  
  262. // By default, audio is u-law encoded to reduce the memory requirement
  263. // in half. However, u-law does add distortion. If "-16" is specified
  264. // on the command line, the original 16 bit PCM samples are used.
  265. for (i=1; i < argc; i++) {
  266. if (strcmp(argv[i], "-16") == 0) pcm_mode = 1;
  267. }
  268. dir = opendir(".");
  269. if (!dir) die("unable to open directory");
  270. while (1) {
  271. f = readdir(dir);
  272. if (!f) break;
  273. //if ((f->d_type & DT_DIR)) continue; // skip directories
  274. //if (!(f->d_type & DT_REG)) continue; // skip special files
  275. if (stat(f->d_name, &s) < 0) continue; // skip if unable to stat
  276. if (S_ISDIR(s.st_mode)) continue; // skip directories
  277. if (!S_ISREG(s.st_mode)) continue; // skip special files
  278. filename = f->d_name;
  279. len = strlen(filename);
  280. if (len < 5) continue;
  281. if (strcasecmp(filename + len - 4, ".wav") != 0) continue;
  282. fp = fopen(filename, "rb");
  283. if (!fp) die("unable to read file %s", filename);
  284. filename2samplename();
  285. printf("converting: %s --> AudioSample%s\n", filename, samplename);
  286. snprintf(buf, sizeof(buf), "AudioSample%s.cpp", samplename);
  287. outc = fopen(buf, "w");
  288. if (outc == NULL) die("unable to write %s", buf);
  289. snprintf(buf, sizeof(buf), "AudioSample%s.h", samplename);
  290. outh = fopen(buf, "w");
  291. if (outh == NULL) die("unable to write %s\n", buf);
  292. fprintf(outh, "%s", title);
  293. fprintf(outc, "%s", title);
  294. fprintf(outc, "#include <Arduino.h>\n");
  295. fprintf(outc, "#include \"%s\"\n\n", buf);
  296. wav2c(fp, outc, outh);
  297. //wav2c(fp, stdout, stdout);
  298. fclose(outc);
  299. fclose(outh);
  300. fclose(fp);
  301. }
  302. printf("Total data size %d bytes\n", total_length * 4);
  303. return 0;
  304. }
  305.  
  306. uint8_t read_uint8(FILE *in)
  307. {
  308. int c1;
  309.  
  310. c1 = fgetc(in);
  311. if (c1 == EOF) die("error, end of data while reading from %s\n", filename);
  312. c1 &= 255;
  313. return c1;
  314. }
  315.  
  316. int16_t read_int16(FILE *in)
  317. {
  318. int c1, c2;
  319.  
  320. c1 = fgetc(in);
  321. if (c1 == EOF) die("error, end of data while reading from %s\n", filename);
  322. c2 = fgetc(in);
  323. if (c2 == EOF) die("error, end of data while reading from %s\n", filename);
  324. c1 &= 255;
  325. c2 &= 255;
  326. return (c2 << 8) | c1;
  327. }
  328.  
  329. uint32_t read_uint32(FILE *in)
  330. {
  331. int c1, c2, c3, c4;
  332.  
  333. c1 = fgetc(in);
  334. if (c1 == EOF) die("error, end of data while reading from %s\n", filename);
  335. c2 = fgetc(in);
  336. if (c2 == EOF) die("error, end of data while reading from %s\n", filename);
  337. c3 = fgetc(in);
  338. if (c3 == EOF) die("error, end of data while reading from %s\n", filename);
  339. c4 = fgetc(in);
  340. if (c4 == EOF) die("error, end of data while reading from %s\n", filename);
  341. c1 &= 255;
  342. c2 &= 255;
  343. c3 &= 255;
  344. c4 &= 255;
  345. return (c4 << 24) | (c3 << 16) | (c2 << 8) | c1;
  346. }
  347.  
  348. void die(const char *format, ...)
  349. {
  350. va_list args;
  351. va_start(args, format);
  352. fprintf(stderr, "wav2sketch: ");
  353. vfprintf(stderr, format, args);
  354. fprintf(stderr, "\n");
  355. exit(1);
  356. }
  357.  
Success #stdin #stdout 0s 5320KB
stdin
Standard input is empty
stdout
Total data size 0 bytes