Okay, just for the record I'm kind of drunk so I'm not entirely sure of this, but... (I started editing it to say that maybe you were right but now I think I was right again, so ...)
I updated the 'loop end condition' (is that the right term) on line 10 to be len /2. |
I used len as the limit since in the update part of the loop I'm adding 2. So the loop will only iterate len/2 times. i will be 0, 2, 4, 6 ... in the loop, so i/2 gives the correct index for the channels and i and i+1 give the correct indices to access the left/right interleaved samples.
EDIT:: Okay, no, I
am wrong here. It should be len/2 even though I'm adding 2. You're right.
result[1] = new float[len / 2]; Surely we need to use len / 2 here as that is the correct buffer length. Also why didn't you allocate any memory on that line? |
Actually, if you're going to do it that way you should allocate len / 4 elements to each channel (assuming len is the number of bytes, not samples, in the audio). Each element of the channel arrays is 2 bytes, and each channel gets half the data, so that's len/4 int16_t's.
But what I was actually doing was using a common idiom in which you allocate all of the floats of the two-dimensional array in one block. That is the "natural" way that a static 2D array would be allocated and it takes up less space. But since your 2D array only has two rows, it's not that much of a savings in this case.
The idea is to allocate two one-dimensional arrays. One is an array of "row pointers", which has a size of 2 in your case. The other is for all of the data, the pointer to which we initially store in the first row pointer (result[0]). Then we set the remaining row pointers to point at the beginning of their rows in the data block. In your case there's only one other row pointer, so we make that one point halfway into the data block (len/4 elements, since each element is 2 bytes).
To delete the data you just need two statements:
1 2
|
delete[] result[0];
delete[] result;
| |
Here's a bit of a readability rewrite:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
float** OSystem_Cli::mixCallback(uint32_t bytes)
{
using SampleType = int16_t;
const uint32_t NumChannels = 2;
const uint32_t NumSamples = bytes / sizeof(SampleType);
auto result = new float*[NumChannels];
result[0] = new float[NumSamples];
result[1] = result[0] + NumSamples / NumChannels;
auto samples = new SampleType[NumSamples];
_mixerImpl->mixCallback((uint8_t*)samples, bytes);
for (uint32_t i = 0; i < NumSamples; i += NumChannels)
{
result[0][i / 2] = samples[i ] / float(1 << 15);
result[1][i / 2] = samples[i + 1] / float(1 << 15);
}
delete[] samples;
return result;
}
| |
BTW, if you really want doubles just change all the "float"s to "double"s.