Converting WAV to C - not working...

Guys, I found some nice Wav to C tools around the net but none work correctly. (at least not 100% correctly)

I get a different size compared to the original WAV file, its like it cuts out something at the end. And in some situations, the start is all wrong.

Any good tools for converting regular 8-bit mono files to c code?

Best Regards, WilliamK

What is WAV? You don't mean music files like songname.wav do you?

Sorry, yes, .wav musical files to c, for things like this:

Here’s an example code:

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
	printf("wav2c v1.00 by Dark Fader / BlackThunder\n");
	if (argc < 2) { printf("Syntax: %s <input.wav>\n", argv[0]); return -1; }
	char buf[1024], *s = buf;
	strcpy(s, argv[1]);
	char *p = strstr(s, ".wav");
	if (!p) { printf("Please specify a 8KHz, 8-bit wav file!\n"); return -1; }
	FILE *fi = fopen(s, "rb");
	if (!fi) { printf("Could not open input file!\n"); return -1; }
	strcpy(p, ".c");
	FILE *fo = fopen(s, "wt");
	if (!fo) { printf("Could not open output file!\n"); return -1; }

	fseek(fi, 0x28, SEEK_SET);
	p = strrchr(s, '\\'); if (p) s = p+1;
	p = strrchr(s, '/'); if (p) s = p+1;
	p = strrchr(s, '.'); if (p) *p = 0;
	fprintf(fo, "const unsigned char %s[] =\n{", s);
	int l=0;
	while (1)
		if (l++ % 100 == 0) { fprintf(fo, "\n\t"); }
		int a = fgetc(fi); if (a == EOF) break;
		fprintf(fo, "%d,", a);

	fprintf(fo, "\n};\n");	

	return 0;

fseek(fi, 0x28, SEEK_SET);

That's ... really awful. According to online sources, .wav files have a relatively complex internal format, possibly containing lots of random data even for any particular sample size and playback. Looks more promising, or something called "wavosaur." These seem to output raw binary; you'll probably need an additional step to convert to C code.

Yup, thanks for the heads up, I also found the code to be very badly written. I will find a way to do my own based on my own. ;-)


The question in this case is: do you need the header for what you are going to do? The tool you were using saves only the raw binary data, and not the header (that is why it is shorter). It also doesn't check if the format you are reading is ok (i.e. bitsize, compression, stereo, samplerate, 2's compliment data etc.).

WilliamK: ...

After modifying wav2c to declare the array to be unsigned char rather than signed char, as indicated in the playground article, I tested wav2c with 8-bit mono wave files at 8000 samples per second.

The only thing that I see wrong is the following statement, on line 181, in wavdata.c:

    realLength = (s->dataLength / s->numChannels / s->bitsPerSample * 8);

If the data length is not an exact multiple of 8, a number of bytes (as many as seven bytes) are truncated to make it a multiple of 8.

The exact expression should be

    realLength = (s->dataLength / s->numChannels / (s->bitsPerSample / 8));

Also, I'm not sure that it is necessary, but as I mentioned, I changed line 243 in wavdata.c from

        fprintf(fpO, "const signed char %s_dataL[]= {", name);


        fprintf(fpO, "const unsigned char %s_dataL[]= {", name);

Note that eight-bit .wav files have their samples stored as unsigned bytes, so declaring the array to be an array of unsigned chars seems to be logical, but it doesn't change the bit patterns of the samples, so you don't have to "convert" anything.

Why not make these two simple changes and try using wav2c? See Footnote.

Then study the code and see what the heck it is doing with the various headers, etc. Note that some .wav files may include lots of extra stuff after the last data sample, and you only want the data sample bytes in the array that Arduino is going to use.

Note that for your use, wav2c requires an 8-bit mono file at 8000 pcm samples per second. It's possible to eliminate code for the other types of file from wavdata.c if you feel the need.

If wav2c doesn't work for you, then how about attaching a small .wav file to your post (one second of 8-bit mono at 8000 samples/sec is 8000 data samples)



Footnote: If you want to write your own conversion program as a learning exercise, then I think that's a Good Thing. Furthermore, I think that having something that already works so that you can compare your output to some good stuff is a Really Good Thing. At some point you will see things that you can improve on, and that means that You Have Arrived!

Dave, thank you so much, I couldn't look at the code, that's why I asked, I was just going nuts reading the PDF for the ATmega328. But at least now I understand better how Timers and PWM works. ;-)


…I couldn’t look at the code…

We have a disconnect somewhere. Your original post indicated that you were looking for tools to convert .wav files to something that could be used in the Arduino playground PCMAudio article. The junky snippet that you posted (from Dark Fader / BlackThunder—gimme a break) is not from the wav2c program at the url that you gave as a reference.

I found Ino Schlaucher’s code at GitHub - olleolleolle/wav2c: wav2c makes arrays out of sounds - useful for Arduino SMAPLER v2 (and for GameBoy Advance) etc to be a somewhat better than “junky.” Actually, a lot better than “junky” for your purpose.

[/Begin edited note] The wav2c from that url works if (and only if) the compiler uses 32-bit ints and 16-bit short ints. This is the case for all of the workstation compilers to which I have access (GNU on 32-bit and 64-bit Linux and 32-bit Windows XP/cygwin, various Microsoft compilers and Borland compilers for 32-bit Windows XP). If anyone has used workstation compilers for which these are not the same, I would like to know. The “right” way is to put assertions in the program to inhibit execution for different sizes and let the user make typedefs appropriate for that particular setup. I know that compilers for embedded systems (like avr-gcc) may have 16-bit ints rather than 32-bit ints, and, in my experience, porting code from one environment to another is somewhat easier if you use <stdint.h> designations instead of “plain vanilla” integer data types in places where size matters. Of course I wouldn’t be porting this particular code to an Arduino, but I thought I would point out a way of using size-dependent things in a way that is a little more robust.

I do something like the following in my programs.

/* GNU compilers have <stdint.h>, some others do not */
#ifdef __GNUC__

    Maybe some other compilers, like recent Borland compilers, also have <stdint.h>
    so use their predefined macros here

#include <stdint.h>
       If your compiler does not have stdint.h, and your
       compiler does not have 16-bit shorts and 32-bit ints,
       then redo the following typedefs to make them
       commensurate with your system. Runtime checks will
       make sure you did it right.
    typedef unsigned char  uint8_t;
    typedef unsigned short uint16_t;
    typedef unsigned int   uint32_t;

#include <assert.h>
int main()
    assert(sizeof(uint16_t) == 2);
    assert(sizeof(uint32_t) == 4);

Then, when referring to header fields where size matters, I use uint16_t and uint32_t instead of short int and int designations. See Footnote.
[/End edited note]



Yes, it’s true: Sometimes size matters!

Ah, yes, I mixed things a bit, sorry for that, doing too many things at once does this to your brain. :astonished:

But thanks for pointing that out, it sure looks like its a much better solution which I can keep and just add some extra layers to check for special wav headers. (later on)


I found Ino Schlaucher's code at to be a somewhat better than "junky." Actually, a lot better than "junky" for your purpose.

Yes; that looks much better than the quoted snippet...

Thanks guys for all the input. I was able to create my own code instead, based on an old code I had. Its not perfect, but its much better. It reads 16 bit files, converts to mono, downsize to 8-bits and outputs the 8-bit unsigned char code for the arduino project.

I will post the code after I clean it up a little. ;-) (its a mess and has a few bugs I'm working on)


interested too :) did you succeed?

Yes, but I haven't got time to fix the bugs yet, will be able too in the other week. ;-)


ok :) how about using real time sample reading from externa memory? could it work?

Indeed, I found a MOD player project that does that. I just posted about it here at the forum. ;-)


Here we go: (all files, examples and source) (windows executable) (source)

It works pretty well here. I will post the code I use for this in another thread. ;-)


hey, thanks a lot worked like a charm!
Is there any way to play back(or convert) the binary sound on a pc?? tried using audacity raw import without success.