12

EZAudio を使用して iOS アプリを作成しています。float**そのデリゲートは、検出されたボリュームを示す float 値を含むバッファーを返します。このデリゲートは常に呼び出され、その作業は別のスレッドで行われます。

私がやろうとしているのは、EZAudio から float 値を取得し、それをデシベルに変換することです。


EZAudioDelegate

マイク データを取得するための簡略化された EZAudio デリゲートを次に示します

- (void)microphone:(EZMicrophone *)microphone hasAudioReceived:(float **)buffer withBufferSize:(UInt32)bufferSize withNumberOfChannels:(UInt32)numberOfChannels {
    /*
     *  Returns a float array called buffer that contains the stereo signal data
     *  buffer[0] is the left audio channel
     *  buffer[1] is the right audio channel
     */

    // Using a separate audio thread to not block the main UI thread
    dispatch_async(dispatch_get_main_queue(), ^{

        float decibels = [self getDecibelsFromVolume:buffer withBufferSize:bufferSize];

        NSLog(@"Decibels: %f", decibels);

    });

}

問題

問題は、以下のリンクからソリューションを実装した後、それがどのように機能するのか理解できないことです. 誰かが音量をデシベルに変換する方法を説明できれば、とても感謝しています


コード

このソリューションでは、Accelerate Frameworkの次のメソッドを使用して、音量をデシベルに変換します。

以下はgetDecibelsFromVolume、EZAudio Delegate から呼び出されるメソッドです。デリゲートからfloat** bufferandが渡されます。bufferSize

- (float)getDecibelsFromVolume:(float**)buffer withBufferSize:(UInt32)bufferSize {

    // Decibel Calculation.

    float one = 1.0;
    float meanVal = 0.0;
    float tiny = 0.1;
    float lastdbValue = 0.0;

    vDSP_vsq(buffer[0], 1, buffer[0], 1, bufferSize);

    vDSP_meanv(buffer[0], 1, &meanVal, bufferSize);

    vDSP_vdbcon(&meanVal, 1, &one, &meanVal, 1, 1, 0);


    // Exponential moving average to dB level to only get continous sounds.

    float currentdb = 1.0 - (fabs(meanVal) / 100);

    if (lastdbValue == INFINITY || lastdbValue == -INFINITY || isnan(lastdbValue)) {
        lastdbValue = 0.0;
    }

    float dbValue = ((1.0 - tiny) * lastdbValue) + tiny * currentdb;

    lastdbValue = dbValue;

    return dbValue;
}
4

1 に答える 1

14

コードを使用して信号の dB 値を計算する方法を説明し、それが vDSP の例にどのように関連するかを示します。

最初に、データのチャンクの RMS 合計を計算します。

double sumSquared = 0;
for (int i = 0 ; i < numSamples ; i++)
{
   sumSquared += samples[i]*samples[i];
}
double rms = sumSquared/numSamples;

RMSの詳細については、

次にRMS値をdBに変換します

double dBvalue = 20*log10(rms);

これがサンプルコードにどのように関係するか

vDSP_vsq(buffer[0], 1, buffer[0], 1, bufferSize);

この行はバッファーをループし、バッファー内のすべての要素の二乗を計算します。呼び出し前にバッファに値が含まれていた場合[1,2,3,4]、呼び出し後に値が含まれます[1,4,9,16]

vDSP_meanv(buffer[0], 1, &meanVal, bufferSize);

この行はバッファーをループし、バッファー内の値を合計してから、合計を要素数で割った値を返します。したがって、入力バッファ[1,4,9,16]の合計を計算し30、除算し4て結果を返します7.5

vDSP_vdbcon(&meanVal, 1, &one, &meanVal, 1, 1, 0);

meanValこの行はをデシベルに変換します。ここでベクトル化された関数を呼び出しても意味がありません。なぜなら、この関数は 1 つの要素に対してのみ動作するからです。ただし、実行しているのは、パラメーターを次の式に差し込むことです。

meanVal = n*log10(meanVal/one)

ここで、最後のパラメーターに応じてまたはのnいずれかです。この場合は です。パワー測定に使用され、振幅に使用されます。使ったほうが分かりやすいと思います。102010102020

コードの最後の部分は、結果を単純に平滑化して、メーターの弾みを少し抑えているようです。

于 2015-02-26T04:35:11.697 に答える