I need to convert between this format :
format.mSampleRate = 44100.0;
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved;
format.mBytesPerPacket = sizeof(AudioUnitSampleType);
format.mFramesPerPacket = 1;
format.mBytesPerFrame = sizeof(AudioUnitSampleType);
format.mChannelsPerFrame = 2 ;
format.mBitsPerChannel = sizeof(AudioUnitSampleType)*8;
and this format
format.mSampleRate = 44100.0;
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical;
format.mBytesPerPacket = sizeof(AudioUnitSampleType);
format.mFramesPerPacket = 1;
format.mBytesPerFrame = sizeof(AudioUnitSampleType);
format.mChannelsPerFrame = 2;
format.mBitsPerChannel = sizeof(AudioUnitSampleType)*8;
within the confines of a audio render callback where there is the following code and buffer[] is in the 2nd format and array[] requires the 1st format.
for (k = 0; k < channels; k++){
buffer = (AudioUnitSampleType *) ioData->mBuffers[k].mData;
for(j=0; j < samples; j++){
array[j] = buffer[j];
}
}
I know you can use the Apple converter unit, but I cannot use the Apple Converter audio unit in my situation (there's a reason).
Basically the only difference between the 2 formats the following flag for format.mFormatFlags (kAudioUnitSampleFractionBits << kLinearPCMFormatFlagsSampleFractionShift).
How can I convert buffer[] (containing data in the 2nd format) to array[] (containing data in the 1st format) and vice-versa?
Thank you.
Maybe a late answer, but since the shifting bits method did not work for me for some reason I found this alternative which is working nicely, in audiograph https://github.com/tkzic/audiograph
I adapted a bit a method from there and voila:
Well, if you refer to the docs on
kAudioFormatFlagsAudioUnitCanonical
, you see:and
So, the samples in
buffer[]
array are in 8.24-bit fixed-point format. What does it mean?8.24-bit fixed-point format is used to represent float numbers with fixed precision - a 32-bit integer where the first 8 bits represent the whole part, and the last 24 bits represent the fractional part (the numbers after the decimal). (Further reading)
In iOS Audio Units, there's a minor difference - this float number (usually) ranges in [-1, 1) ([-1.000000000000, +0.999969482421875] to be exact). Values outside of this range are simply clipped when converting to 16-bit PCM. You can validate that the first 8 bits would be 0x00 or 0xff (-1 in two's compliment) for most part.
To convert this representation to a 16-bit number, use this:
That is: extract the sign from the 8 MSB, extract fractional value from 24 LSB and divide by range of 24-bit integer (2^24) resulting in a float between 0 and 1, and finally multiply this by 32768 to get a value in desired range.
I haven't tried this myself though - you might have to adjust a few things here and there.