如何正确填充立体声AudioBuffer

时间:2011-05-22 23:24:21

标签: ios audio audiounit

所以我正在使用Apple的MixerHost sample code来进行立体声合成的基本听力设置。我在弄清楚如何填充缓冲切片时遇到了一些麻烦。具体来说,我只在左声道输出音频,右声道静音:

AudioUnitSampleType *buffer = (AudioUnitSampleType *)ioData->mBuffers[0].mData;    
SInt16 sampleValue;

for(UInt32 i = 0; i < inNumberFrames; i++)
{
    sampleValue = sinf(inc) * 32767.0f; // generate sine signal
    inc += .08;

    buffer[i] = sampleValue;
}

if(inc > 2e10) inc -= 2e10;

这会在左声道上播放一个正弦波......音调类型每10秒左右发生变化,另一个指示我做错了:]

我尝试过其他方法来逐步完成阵列。这产生了有趣的声音,远离正弦信号。有一次,我在两个频道上都出现了毛刺/波动的输出,这有点像成功。

如果我检查AudioBuffer结构,它确认有2个通道,每帧的字节大小为4.所以每帧有两个SInt16,对吗?一个用于左侧,一个用于右侧通道..它们应该是交错的?

请注意,我使用的流格式与Apple的示例不同,因为我不知道定点数学。

流格式设置如下:

size_t bytesPerSample = sizeof (AudioUnitSampleType);

stereoStreamFormat.mFormatID          = kAudioFormatLinearPCM;
stereoStreamFormat.mFormatFlags       = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
stereoStreamFormat.mBytesPerPacket    = bytesPerSample;
stereoStreamFormat.mFramesPerPacket   = 1;
stereoStreamFormat.mBytesPerFrame     = bytesPerSample;
stereoStreamFormat.mChannelsPerFrame  = 2;                    
stereoStreamFormat.mBitsPerChannel    = 8 * bytesPerSample;
stereoStreamFormat.mSampleRate        = graphSampleRate;

所以我的问题是,如何填充上面设置的立体声缓冲区,以便它能正常工作?

谢谢!

2 个答案:

答案 0 :(得分:2)

查看Classes/MixerHostAudio.m示例中的MixerHost,然后向下滚动到他们定义的位置,并指定outSamplesChannelLeftoutSamplesChannelRight。看起来API期望左侧和右侧样本位于不同的缓冲区中,而不是交错的。

至于改变音高,试试

if (inc > M_PI) inc -= 2.0*M_PI;

(或Apple定义的任何代替M_PI)并在循环内执行此操作,而不是在填充整个框架之后。浮点错误累积得非常快。上面的更正使用了sin超过2*pi的事实。你的修正任意地将inc包裹回来,如果包裹不是相位连续的话,会在包裹点引起毛刺。

最后,我不清楚你的bytesPerSample是否为2,你可能想检查一下。如果是,那么我猜你关于bytesPerFrame的其他假设是正确的。

答案 1 :(得分:1)

您正在设置mBytesPerFrame = bytesPerSample。这仅允许每帧一个样本。对于交错立体声(即mChannelsPerFrame = 2),每帧需要两个样本。尝试设置mBytesPerFrame = 2 * bytesPerSample.

在渲染功能中:

UInt32 numOfSamples = 2 * inNumberFrames;
for (i = 0; i < numOfSamples; i+=2) {
 buffer[i] = //assign left channel value;
 buffer[i+1] = //assign right channel value;
}