My main concern is how to split the bit rate of 38,500 into the two bytes provided for that info. And of course, I'll still be creating a mono file with one byte per sample.
Also, I'm wondering if the bit rate of 38,500 can be understood by players reading my file? I'm not sure since the standard for CD's is 44,100. Evidently the ATmega328 interrupt timers can't easily be set for 44,100 since the sketch is set to 38,500 instead.
// wavheader setup
// little endian (lowest byte 1st)
wavheader[0]='R';
wavheader[1]='I';
wavheader[2]='F';
wavheader[3]='F';
//wavheader[4] to wavheader[7] size of data + header -8
wavheader[8]='W';
wavheader[9]='A';
wavheader[10]='V';
wavheader[11]='E';
wavheader[12]='f';
wavheader[13]='m';
wavheader[14]='t';
wavheader[15]=' ';
wavheader[16]=16;
wavheader[17]=0;
wavheader[18]=0;
wavheader[19]=0;
wavheader[20]=1;
wavheader[21]=0;
wavheader[22]=1;
wavheader[23]=0;
// wavheader[24] to wavheader[27] samplerate hz
// wavheader[28] to wavheader[31] samplerate*1*1
// optional bytes can be added here
wavheader[32]=1;
wavheader[33]=0;
wavheader[34]=8;
wavheader[35]=0;
wavheader[36]='d';
wavheader[37]='a';
wavheader[38]='t';
wavheader[39]='a';
//wavheader[40] to wavheader[43] sample number
There isn't a field for bit rate in the WAV header. There is a 32-bit field for sample rate which will easily hold 38500.
There is also a 32-bit field for byte rate which is simply the sampling rate multiplied by the number of bytes per sample (which is also a field in the header). In your case this will also be 38500.
Combining what you said with the below web page I just found, I think I now have the answer. Big and Little Endian (the sample I gave saying "Little Endian" at the top)
I can't test it yet to be sure, but I believe this will work:
I opened the windows calculator program in "programmer" mode, set it to "Dec", and entered 38500.
I changed from "Dec" to "Hex", which changed the number to 9664.
I entered just the high byte "96", changed back to "Dec, and got "100".
I changed to "Hex" again, and entered the low byte "64".
I changed this back to "Dec", and got "150".
So I've entered those two numbers -- "100" and "150" -- in my sketch as shown:
Your code would be easier to read, especially when you come back to it after a few weeks, if you defined a structure for the WAV header and filled in each of the named fields. Something like this:
struct soundhdr {
char riff[4]; /* "RIFF" */
long flength; /* file length in bytes */
char wave[4]; /* "WAVE" */
char fmt[4]; /* "fmt " */
long chunk_size; /* size of FMT chunk in bytes (usually 16) */
short format_tag; /* 1=PCM, 257=Mu-Law, 258=A-Law, 259=ADPCM */
short num_chans; /* 1=mono, 2=stereo */
long srate; /* Sampling rate in samples per second */
long bytes_per_sec; /* bytes per second = srate*bytes_per_samp */
short bytes_per_samp; /* 2=16-bit mono, 4=16-bit stereo */
short bits_per_samp; /* Number of bits per sample */
char data[4]; /* "data" */
long dlength; /* data length in bytes (filelength - 44) */
} wavh;
// ......
// It's easy enough to initialize the strings
strncpy(wavh.riff,"RIFF",4);
strncpy(wavh.wave,"WAVE",4);
strncpy(wavh.fmt,"fmt ",4);
strncpy(wavh.data,"data",4);
// size of FMT chunk in bytes
wavh.block_size = 16;
wavh.format_tag = 1; // PCM
wavh.num_chans = 1; // mono
// This is easier than converting to hex and then to bytes :)
wavh.srate = 38500;
wavh.bits_per_samp = 8;
// etc.
I didn't know I could do that, Pete. Besides being easier to read, entering the data -- without all the above switching between DEC and HEX on a calculator first -- is SO much easier.
Woops! Pete, your "struct" didn't work when it came time to save it to the SD Card.
The line:
myFile.write(wavheader, 44);
worked fine when it was a simple string of bytes, but now that its a complex structure containing several types, you have to explicitly tell it to save it as a string of bytes anyway; using: