Separating Out the Mixing - richardjwild/arctracker GitHub Wiki
Next I turned my attention to the output_data function. This was doing two things: mixing down the channels into a single stereo audio data buffer, and then calling the appropriate API to output the sound. I wanted to put the mixing into a separate file so I moved the audio API calls up into write_audio_data and created mix.c where I put the code for mixing the audio channels down. I also made mix.c responsible for allocating the audio output buffer. This change took quite a while to debug, the details of which I won't bore you with here.
The next thing was this awkward byte manipulation code:
audio_buffer[audio_buffer_index++] = (unsigned char) (lval & 0xff);
audio_buffer[audio_buffer_index++] = (unsigned char) ((lval >> 8) & 0xff);
audio_buffer[audio_buffer_index++] = (unsigned char) (rval & 0xff);
audio_buffer[audio_buffer_index++] = (unsigned char) ((rval >> 8) & 0xff);
I really don't understand why I thought that I had to do everything myself back then. So I declared the audio buffer in terms of __int16_t instead of unsigned char and managed to replace six lines of code with two.
The most important factor in clean code is good naming, so I took the opportunity to improve some of the names.
Now that mix.c was responsible for allocating the audio buffer, it could remember the buffer size, which enabled me to remove a parameter from the mix function.
Finally, I thought better about the names of my constants and then I inlined the clip function and added the -Winline flag so that gcc would warn me if any of the inline-declared functions could not be inlined (all of them could be).
Previous: How I Learned to Love Floating point Arithmetic | Next: Audio Output Strategies