Tonight’s small victory: sample conversion to 16-bits


Oy, Objective C is kicking my butt. 🙁 It has been so long since I have had to deal with pointers I am very rusty with pointer arithmetic. But tonight was a victory of sorts.

I loaded up a snare PCM sample I’m using as a test sound for a (hopefully) upcoming iOS app. It is a stereo, 32-bit WAV file, 44.1 KHz, and 94636 bytes. The other night I thought my calculations were slightly off, but that’s just because the first 44 bytes are just a WAV header—I’m sure I knew that at some point. So that means each sample frame (a frame having all the channels’ values at a point in time) is 8 bytes: 4 bytes for the left channel, 4 bytes for the right channel. The challenge was to convert this into a normalized format in the iPad’s memory.

So some light math needed to be applied to allocate 2 buffers: one for data coming off of disk and one for the converted sample. The thing is, AVAssetReader reads in chunks. So it took me a bit of searching to find out how to use NSMutableData. A conversion method steps through each sample in the input buffer and writes it to the output buffer but converted to 16-bits. (Yay, bitshifting!)

I did some calculations in Adobe Audition to see if my numbers were sane: it’s 0:00.268 sec long. Checking: (94636 bytes – 44 bytes)/44100/8 turns out to be 0.268117914. Bingo. So the size of the file and playtime are correct. And, since that’s a 32-bit file and I’m turning it into 16-bit in memory, I should be allocating a buffer that is half of 94592 bytes, and it turns out I do in fact come up with the correct number: 47296.