1

進歩的な洞察のために質問を編集しました:-)

音声入力をリッスンするアプリを作成しています。ピークを数えてほしい。(ピークは約10 Hzの最大周波数になります。)

多くの検索を行った後、生の入力データを取得できるAudioQueueサービスを使用することになりました。SpeakHereの例の簡略版(再生なし)を使用していますが、単にファイルシステムにバッファーを書き込むのではなく、個々のサンプルデータを確認したいと思います。

私は今正しい方向に進んでいると思いますが、バッファの操作方法がわかりません。1つのサンプルのデータを分離しようとしています。次の関数のforループでは、それは意味がありますか?1つのサンプルを取得するには、そこに何を入れる必要がありますか?

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

おそらく、ピーク電力レベルに何らかの平滑化を適用したいと思うでしょう。おそらくIIRフィルターで、次のようなものです。

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

私はこの機能を使用したことがないので、それがあなたが望むすべてを行うかどうかはわかりません。そうでない場合は、レベルを下げてRemoteIOオーディオユニットを使用し、「入力コールバック」を使用して着信時にサウンドをキャッチできます(スピーカーがデータに飢えているときに発生するレンダリングコールバックとは対照的です)

入力コールバックでは、独自のバッファーを作成する必要があることに注意してください。最後のパラメーターとしてバッファーポインターを取得したからといって、それが有効なものを指しているとは考えないでください。そうではありません。

とにかく、いくつかのvDSP関数を使用して、バッファー全体のベクトルの大きさの2乗を取得できます(1024フロートまたはバッファーサイズ/ストリーム形式が何であれ)

そして、あなたはそれを自分で滑らかにすることができます

于 2011-06-24T13:43:27.583 に答える
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 に答える