Также необходимо обновить размеры.
В Core Audio сэмпл - это одно единственное значение, а кадр - это один сэмпл по всем каналам. Для звука PCM один кадр также является одним пакетом.
Для 16-битного монофонического звука кадр и образец являются синонимами и занимают 2 байта. Для 16-битного стереозвука кадр состоит из двух отсчетов (левого и правого), каждый из которых занимает 2 байта, а каждый кадр занимает 4 байта.
Значения AudioStreamBasicDescription
незначительно различаются в зависимости от того, описываемый формат чередуется или нет.
Обычно вы можете думать о без чередования PCM AudioStreamBasicDescription
s следующим образом:
asbd.mBytesPerFrame = asbd.mBitsPerChannel / 8;
и с чередованием вот так:
asbd.mBytesPerFrame = (asbd.mBitsPerChannel / 8) * asbd.mChannelsPerFrame;
с оба с
asbd.mFramesPerPacket = 1;
asbd.mBytesPerPacket = asbd.mBytesPerFrame;
AudioFormatFlags.Canonical
устарело, но я предполагаю, что здесь это приравнивается к чередующемуся упакованному native- endian целые числа со знаком.
Итак, для вашего случая 16-битное стерео с чередованием:
AudioStreamBasicDescription outputFormat = new AudioStreamBasicDescription();
outputFormat.setFormat(AudioFormat.LinearPCM);
outputFormat.setFormatFlags(AudioFormatFlags.Canonical);
outputFormat.setSampleRate(pitch);
outputFormat.setChannelsPerFrame(2);
outputFormat.setBitsPerChannel(16);
outputFormat.setBytesPerFrame(4);
outputFormat.setFramesPerPacket(1);
outputFormat.setBytesPerPacket(4);
Вот две вспомогательные функции (в C ++), показывающие отношения:
static AudioFormatFlags CalculateLPCMFlags(UInt32 validBitsPerChannel, UInt32 totalBitsPerChannel, bool isFloat, bool isBigEndian, bool isNonInterleaved)
{
return (isFloat ? kAudioFormatFlagIsFloat : kAudioFormatFlagIsSignedInteger) | (isBigEndian ? ((UInt32)kAudioFormatFlagIsBigEndian) : 0) | ((validBitsPerChannel == totalBitsPerChannel) ? kAudioFormatFlagIsPacked : kAudioFormatFlagIsAlignedHigh) | (isNonInterleaved ? ((UInt32)kAudioFormatFlagIsNonInterleaved) : 0);
}
static void FillOutASBDForLPCM(AudioStreamBasicDescription *asbd, Float64 sampleRate, UInt32 channelsPerFrame, UInt32 validBitsPerChannel, UInt32 totalBitsPerChannel, bool isFloat, bool isBigEndian, bool isNonInterleaved)
{
asbd->mFormatID = kAudioFormatLinearPCM;
asbd->mFormatFlags = CalculateLPCMFlags(validBitsPerChannel, totalBitsPerChannel, isFloat, isBigEndian, isNonInterleaved);
asbd->mSampleRate = sampleRate;
asbd->mChannelsPerFrame = channelsPerFrame;
asbd->mBitsPerChannel = validBitsPerChannel;
asbd->mBytesPerPacket = (isNonInterleaved ? 1 : channelsPerFrame) * (totalBitsPerChannel / 8);
asbd->mFramesPerPacket = 1;
asbd->mBytesPerFrame = (isNonInterleaved ? 1 : channelsPerFrame) * (totalBitsPerChannel / 8);
}