【问题标题】:how to properly fill a stereo AudioBuffer如何正确填充立体声 AudioBuffer
【发布时间】:2011-08-30 19:04:18
【问题描述】:

所以我正在使用 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;

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

谢谢!

【问题讨论】:

    标签: ios audio audiounit


    【解决方案1】:

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

    至于改变音高,试试

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

    (或 Apple 定义的任何代替 M_PI)并在循环中执行此操作,而不是在填充整个帧之后。浮点误差累积得惊人地快。上面的更正使用了sin2*pi 上是周期性的这一事实。您的更正会任意将inc 回卷,如果回卷不是相位连续的,则会导致在回卷点出现故障。

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

    【讨论】:

    • 关于两个不同的缓冲区,当我检查 *ioData AudioBufferList 时,它说 mBuffers 数组的大小为 1。不过,我得到的一个 AudioBuffer 有两个通道,这就是它在盒子上所说的。我认为这是由于使用了与 MixerHost 示例不同的流格式,我从另一个示例中获取了该示例来绕过定点数学:kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked 而不是 kAudioFormatFlagsAudioUnitCanonical
    • 如果我是你,我会不理会格式标志。您正在使用浮点数学,但将结果转换回整数,所以我认为您不必担心。
    • 好的,我现在正在使用kAudioFormatFlagsAudioUnitCanonical,这令人惊讶地与您建议的演员阵容配合使用,但是由于某种原因输出音量非常低......如果我提高幅度,音频开始剪辑而不增加音量。 bytesPerSample 是 4..
    • 我有点飘在这里,所以只是发布正在发生的事情......如果我得到一个指向缓冲区的空指针,如下所示:void *buffer = ioData-&gt;mBuffers[0].mData; 然后像这样在循环中遍历它:*(AudioUnitSampleType*)buffer = sampleValue; buffer+=8; 我得到一个立体声信号。没有正弦信号,更像是脉冲/相位的东西。但这表明缓冲区确实是交错的……不知何故……将指针增加 4 产生的结果与在左侧通道上使用 [i].. 正弦遍历数组时产生的结果相同..
    • 如果bytesPerSample 是4,你不应该按2**31 缩放吗?如果我没记错的话,你在调用AudioQueueAllocateBuffer 时声明了缓冲区的数量。不过,已经有一段时间没有做任何 Core Audio 的东西了,所以这可能不太正确。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2020-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多