如何正确填充立体声音频缓冲区

发布于 2024-11-09 05:42:24 字数 1483 浏览 2 评论 0原文

所以我使用苹果的 MixerHost示例代码用于进行立体声合成的基本听力记录设置。我在弄清楚如何填充缓冲区切片时遇到了一些麻烦。具体来说,我只在左声道中输出音频,右声道是静音的:

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;

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

谢谢!

so i'm using Apple's MixerHost sample code to do a basic audiograph setup for stereo synthesis. I have some trouble figuring out how i have to fill the buffer slice. Specifically, i get audio out only in the left channel, the right channel is silent:

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;

This plays a sine wave on the left channel... The pitch kind of changes every 10 seconds or so, another indicator that i'm doing it wrong :]

i've tried other ways of stepping through the array. this produced interesting sounds which were far from a sine signal. At one point i had glitchy/choppy output on both channels, which was kind of like a success.

If i inspect the AudioBuffer struct, it confirms there are 2 channels, and the bytesize per frame is 4. So per frame, there are two SInt16, right? One for left, and one for the right channel.. and they are supposed to be interleaved?

Note that i am using a stream format that is different from Apple's example because i don't know fixed point math.

The stream format is setup like so:

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;

so my question is, how do i fill a stereo buffer which is setup like above with data so that it just works?

thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一场信仰旅途 2024-11-16 05:42:24

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

至于改变音高,请尝试

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

(或 Apple 定义的任何替代 M_PI)并在循环内执行此操作,而不是在填充整个帧之后。浮点错误的累积速度惊人地快。上述修正利用了 sin2*pi 上具有周期性的事实。您的校正会任意将 inc 重新包裹起来,如果包裹不是相位连续的,则会在包裹点处导致故障。

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

Take a look at Classes/MixerHostAudio.m in the MixerHost example, and scroll down to where they define and assign outSamplesChannelLeft and outSamplesChannelRight. It looks like the API expects left and right samples in different buffers, not interleaved.

As for the changing pitch, try

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

(or whatever Apple defines in place of M_PI) and do this within the loop, not after filling the whole frame. Floating point error accumulates surprisingly quickly. The correction above uses the fact that sin is periodic over 2*pi. Your correction arbitrarily wraps inc back in, and will cause a glitch at the wrap point if the wrapping isn't phase continuous.

And finally, it's not clear to me if your bytesPerSample is 2 or not, you might want to check this. If it is, then I'd guess your other assumption about bytesPerFrame is correct.

怂人 2024-11-16 05:42:24

您正在设置 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;
}

You are setting mBytesPerFrame = bytesPerSample. This only allows one sample per frame. For interleaved stereo (i.e. mChannelsPerFrame = 2) you need two samples per frame. Try setting mBytesPerFrame = 2 * bytesPerSample.

In your render function:

UInt32 numOfSamples = 2 * inNumberFrames;
for (i = 0; i < numOfSamples; i+=2) {
 buffer[i] = //assign left channel value;
 buffer[i+1] = //assign right channel value;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文