10

Appleがここで話す例で使用している数学について質問があります。

少し背景:AVAudioRecorderとAVAudioPlayerによって返される平均電力とピーク電力はdB単位であることがわかっています。また、RMS電力がdB単位である理由と、を使用してアンプに変換する必要があることも理解していますpow(10, (0.5 * avgPower))

私の質問は:

Appleはこの式を使用して、「メーターテーブル」を作成します

MeterTable::MeterTable(float inMinDecibels, size_t inTableSize, float inRoot)
    : mMinDecibels(inMinDecibels),
    mDecibelResolution(mMinDecibels / (inTableSize - 1)), 
    mScaleFactor(1. / mDecibelResolution)
{
    if (inMinDecibels >= 0.)
    {
        printf("MeterTable inMinDecibels must be negative");
        return;
    }

    mTable = (float*)malloc(inTableSize*sizeof(float));

    double minAmp = DbToAmp(inMinDecibels);
    double ampRange = 1. - minAmp;
    double invAmpRange = 1. / ampRange;

    double rroot = 1. / inRoot;
    for (size_t i = 0; i < inTableSize; ++i) {
        double decibels = i * mDecibelResolution;
        double amp = DbToAmp(decibels);
        double adjAmp = (amp - minAmp) * invAmpRange;
        mTable[i] = pow(adjAmp, rroot);
    }
}

すべての計算は何ですか?つまり、これらの各ステップは何をしますか?私はそれを考えてmDecibelResolutionおりmScaleFactor、400の値を超える80dBの範囲をプロットするために使用されています(私が間違っていない限り)。ただし、、、およびの重要性inRootは何ampRangeですか?さらに、メーターテーブルのi番目のエントリが「」であるのはなぜですか。invAmpRangeadjAmpmTable[i] = pow(adjAmp, rroot);

どんな助けでも大歓迎です!:)

よろしくお願いします!

4

2 に答える 2

9

私がこの質問をしてから1か月が経ちました。そして、Geebs、あなたの回答に感謝します!:)

ですから、これは私が取り組んでいるプロジェクトに関連していて、これに基づく機能は、その質問をしてから約2日後に実装されました。明らかに、私は締めくくりの返答を投稿するのを怠りました(それについては申し訳ありません)。1月7日にもコメントを投稿しましたが、振り返ってみると、var名に戸惑っていたようです。>_<。私はこの質問に(写真付きで)完全な行ごとの答えを与えると思いました。:)

だから、ここに行きます:

//mDecibelResolution is the "weight" factor of each of the values in the meterTable.
//Here, the table is of size 400, and we're looking at values 0 to 399.
//Thus, the "weight" factor of each value is minValue / 399.


MeterTable::MeterTable(float inMinDecibels, size_t inTableSize, float inRoot)
    : mMinDecibels(inMinDecibels),
    mDecibelResolution(mMinDecibels / (inTableSize - 1)), 
    mScaleFactor(1. / mDecibelResolution)
{
    if (inMinDecibels >= 0.)
    {
        printf("MeterTable inMinDecibels must be negative");
        return;
    }

    //Allocate a table to store the 400 values
    mTable = (float*)malloc(inTableSize*sizeof(float));

    //Remember, "dB" is a logarithmic scale.
    //If we have a range of -160dB to 0dB, -80dB is NOT 50% power!!!
    //We need to convert it to a linear scale. Thus, we do pow(10, (0.05 * dbValue)), as stated in my question.

    double minAmp = DbToAmp(inMinDecibels);

    //For the next couple of steps, you need to know linear interpolation.
    //Again, remember that all calculations are on a LINEAR scale.
    //Attached is an image of the basic linear interpolation formula, and some simple equation solving.

線形補間方程式

    //As per the image, and the following line, (y1 - y0) is the ampRange - 
    //where y1 = maxAmp and y0 = minAmp.
    //In this case, maxAmp = 1amp, as our maxDB is 0dB - FYI: 0dB = 1amp.
    //Thus, ampRange = (maxAmp - minAmp) = 1. - minAmp
    double ampRange = 1. - minAmp;

    //As you can see, invAmpRange is the extreme right hand side fraction on our image's "Step 3"
    double invAmpRange = 1. / ampRange;

    //Now, if we were looking for different values of x0, x1, y0 or y1, simply substitute it in that equation and you're good to go. :)
    //The only reason we were able to get rid of x0 was because our minInterpolatedValue was 0.

    //I'll come to this later.
    double rroot = 1. / inRoot;

    for (size_t i = 0; i < inTableSize; ++i) {
        //Thus, for each entry in the table, multiply that entry with it's "weight" factor.
        double decibels = i * mDecibelResolution;

        //Convert the "weighted" value to amplitude using pow(10, (0.05 * decibelValue));
        double amp = DbToAmp(decibels);

        //This is linear interpolation - based on our image, this is the same as "Step 3" of the image.
        double adjAmp = (amp - minAmp) * invAmpRange;

        //This is where inRoot and rroot come into picture.
        //Linear interpolation gives you a "straight line" between 2 end-points.
       //rroot =  0.5
       //If I raise a variable, say myValue by 0.5, it is essentially taking the square root of myValue.
       //So, instead of getting a "straight line" response, by storing the square root of the value,
       //we get a curved response that is similar to the one drawn in the image (note: not to scale).
        mTable[i] = pow(adjAmp, rroot);
    }
}

応答曲線の画像:ご覧のとおり、「線形曲線」は正確には曲線ではありません。> _ < 平方根応答画像

これが何らかの形でコミュニティに役立つことを願っています。:)

于 2013-01-22T22:59:41.683 に答える
2

専門家はいませんが、物理学と数学に基づいています。

最大振幅が1、最小振幅が0.0001であると想定します[-80dbに対応します。これは、アップルの例で設定されている最小db値です:#define kMinDBvalue -80.0 in AQLevelMeter.h]

minAmpは、この例の最小振幅=0.0001です。

これで、デシベル分解能の倍数の振幅が最小振幅に対して調整されるだけです。
調整された振幅=(amp-minamp)/(1-minamp)
これにより、調整された振幅の範囲が0から1になります。 0.0001から1の代わりに(それが必要な場合)。

ここでは、inRootは2に設定されています。rroot=1/2-1/2の累乗は平方根です。Appleのファイルから:
//inRoot-これは応答の曲率を制御します。2.0は平方根、3.0は立方根です。ただし、inRootは整数値である必要はなく、1.8や2.5などになり
ます。基本的に0から1の間の応答が得られ、その曲率はinRootに設定した値によって異なります。

于 2012-12-29T07:48:45.753 に答える