1

由于渐进的见解而编辑了问题:-)

我正在创建一个正在收听音频输入的应用程序。我希望它计算峰值。(峰值将在大约 10 Hz 的最大频率处。)

经过大量搜索,我最终使用了 AudioQueue 服务,因为它可以为我提供原始输入数据。我正在使用 SpeakHere 示例的精简版本(不播放),但不是简单地将缓冲区写入文件系统,我想查看单个样本数据。

认为我现在走在正确的轨道上,但我不明白如何使用缓冲区。我正在尝试隔离一个样本的数据。因此,以下函数中的 for 循环是否有意义,我应该在其中放入什么来获取一个样本?

void AQRecorder::MyInputBufferHandler( void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumPackets, const AudioStreamPacketDescription* inPacketDesc)
{
    // AudioQueue callback function, called when an input buffers has been filled.

    AQRecorder *aqr = (AQRecorder *)inUserData;
    try {
        if (inNumPackets > 0) {
            /*          // write packets to file
            XThrowIfError(AudioFileWritePackets(aqr->mRecordFile,FALSE,inBuffer->mAudioDataByteSize,inPacketDesc,aqr->mRecordPacket,&inNumPackets,inBuffer->mAudioData),
                      "AudioFileWritePackets failed");*/

            SInt16 sample;
        for (UInt32 sampleIndex=0; sampleIndex < inNumPackets; ++sampleIndex) {


            // What do I put here to look at one sample at index sampleIndex ??


        }
        aqr->mRecordPacket += inNumPackets;
        }

    // if we're not stopping, re-enqueue the buffe so that it gets filled again
    if (aqr->IsRunning())
        XThrowIfError(AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL),
                      "AudioQueueEnqueueBuffer failed");
    } catch (CAXException e) {
    char buf[256];
    fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
}
}

(也许我不应该删除这么多原来的问题……政策是什么?)

最初我正在考虑使用 AurioTouch 示例,但正如评论中指出的那样,它使用吞吐量,我只需要输入。这也是一个比 SpeakHere 复杂得多的例子。

4

2 回答 2

0

这将遍历缓冲区中的所有样本。

    SInt16 sample;
    for (UInt32 sampleIndex=0; sampleIndex < inNumPackets; ++sampleIndex) {
        sample = buffer[sampleIndex]; // Get the power of one sample from the buffer
        aqr->AnalyseSample(sample);
    }

这是一个棘手的部分:aqr 指向记录器的实例。回调是静态函数,不能直接访问成员变量或成员函数。

为了计算峰值,我记录了一个长期平均值和一个短期平均值。如果短期平均值比长期平均值大某个因素,则存在峰值。当短期平均线再次下跌时,峰值已经过去。

于 2011-07-13T08:11:29.170 回答
0

您可能希望对峰值功率水平应用某种平滑,也许是 IIR 滤波器,例如:

x_out = 0.9 * x_old + 0.1 * x_in;
:
x_old = x_out;

我没有使用过这个功能,所以我不知道它是否能满足你的所有需求。如果没有,您可以降低一个级别并使用 RemoteIO 音频单元,并使用“输入回调”捕捉声音(与扬声器渴望数据时发生的渲染回调相反)

请注意,在输入回调中,您必须创建自己的缓冲区,不要仅仅因为您将缓冲区指针作为最后一个参数而认为它指向有效的东西。它没有。

无论如何,您可以使用一些 vDSP 函数来获得整个缓冲区的向量的幅度平方(1024 个浮点数或任何您的缓冲区大小/流格式)

然后你可以自己平滑

于 2011-06-24T13:43:27.583 回答