Squeezing audio samples into Arduino memory
I digitized 6 seconds of a guitar string sound, on a single channel (i.e. monophonic) using a 44.1 kHz sampling rate, so the digitized sound contained:
44100 samples/s * 6 s = 264600 samples
Each sample from my PC audio interface is stored into 16 bits (2 bytes), so the total amount of memory required is:
264600 samples * 2 bytes = 529200 bytes
Ooops, the Arduino Uno microcontroller only has 32 KB of Flash memory… and that has to include the program too!
Not good. A compromise is needed: the art of optimization is about finding the best trade-off among conflicting requirements.
Audio budget cuts
The first obvious thing to do is to reduce the size of a sample: using 8 bits instead of 16 bits halves the required memory. The sound quality will suffer (more on this later) but in a sense it would be fitting for a ‘retro’ project on an 8-bit microcontroller. However:
264600 samples * 1 byte = 264600 bytes
It would still require way too much memory, so I could reduce the sampling rate from 44.1 kHz to 22.05 kHz:
22050 samples/s = 22050 bytes/s * 6 s = 132300 bytes
No way to fit these into the available 32768 bytes (minus the memory used by the program), so I must also reduce the duration of the digitized audio.
Here it is convenient to reason backwards: how much Flash memory can I spare to contain the guitar sound?
The player program will be small, probably a few kilobytes. If I reserve 8 KB for the program, the guitar sound must fit into the remaining 24 KB, i.e. 24576 samples at most.
What would be the duration of a digitized sound made of 24576 samples, played out at 22050 samples/s?
24576 / 22050 = about 1.11 s
I actually chose a sligthly different compromise: I kept the original 44.1 kHz sampling frequency and further halved the playing time:
sampling rate: 44100 Hz
numer of samples: about 24000
duration: about 0.6 s
Keeping a higher sampling frequency, i.e. a more finely defined original signal, helps in reducing undesired effects such as intermodulation distortion (more on this later), in this case at the cost of a shorter sound.
Reshaping a sound with Audacity
I had to shorten the 6-second digitized sound to 0.6-seconds, at the same time trying not to completely lose its timbric quality: I hoped it could still sound like a sort of guitar string.
I opted to build a ‘half-fake’ guitar sound: I kept only the first 0.6 seconds of the original sound, but I reshaped this shorter sound using the Audacity “envelope” tool to get a faster decay, i.e. the decreasing of volume with time:
The net effect of this operation is that the sound is much shorter than the original, but its volume shape (the ‘envelope’) is similar. Also note how I cut off the ending with a final, faster decay when the allotted time is about to expire.
Listen to the reshaped sound:
It sounds more or less like the string of a cheap guitar, whose sound is dampened with a fingertip after a little while. The guitar from which I took the original sound was deeply offended, but it could be worse.
Next time: how to play this sound at different frequencies, to produce the desired notes.
Can you provide me the code for this project?
You can download it from here:
/www.erix.it/play-v6
P.S. The link I posted is not what is described in the post you commented, but its latest evolution.