2012-12-18 18 views
10

我有一個關於蘋果在其中使用的數學問題speak here example蘋果在這裏說話的數學例子

小背景:我知道AVAudioRecorder和AVAudioPlayer返回的平均功率和峯值功率是以dB爲單位的。我也明白爲什麼RMS功率是以dB爲單位的,它需要使用pow(10, (0.5 * avgPower))轉換成放大器。

我的問題存在:

蘋果使用這個公式來打造它的「米表」

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); 
    } 
} 

什麼是所有的計算 - 或者說,有什麼事情的每個步驟呢?我認爲mDecibelResolutionmScaleFactor用於繪製超過400個值的80dB範圍(除非我錯了)。但是,inRootampRange,invAmpRangeadjAmp的意義是什麼?另外,爲什麼米表中的第i個條目「mTable[i] = pow(adjAmp, rroot);」?

任何幫助非常感謝! :)

在此先感謝和歡呼!

回答

8

自從我提出這個問題已經過了一個月,謝謝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. 

Linear Interpolation Equation

//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); 
    } 
} 

響應曲線圖像:正如你所看到的, 「線性曲線」 是不完全的曲線。 > _ < Square root response image

希望能夠以某種方式幫助社區。 :)

2

專家,但基於物理和數學:

假設最大振幅爲1,最低爲0.0001相當於-80dB,這是最小分貝值在蘋果例如設置爲:#定義kMinDBvalue -80.0在AQLevelMeter.h]

minAmp是最小幅度= 0.0001這個例子

現在,所有正在做的是在分貝分辨率的倍數的幅度被調整對最小振幅:調整幅度=(amp-minamp)/(1-minamp)
這使調整幅度的範圍= 0到1而不是0.0001到1(如果需要的話)。

inRoot在這裏設置爲2。 rroot = 1/2 - 提升到1/2的功率是平方根。從蘋果的文件:
// inRoot - 這控制響應的曲率。 2.0是平方根,3.0是立方根。但inRoot不一定是整數值,它可以是1.8或2.5等。
本質上會再次給出0和1之間的響應,並且曲率根據您爲inRoot設置的值而變化。

+0

感謝您的迴應!所以,如果我正確地理解了這一點,那麼adjAmp本質上是以0到1的比例繪製的-80到0的線性內插值,確保我們只繪製了400個值(在本例中)?然後烙鐵基本上使它「非線性」,但更多的曲線響應?謝謝! – codeBearer

+0

將-80db的已調整放大器線性內插值調用爲0是錯誤的。線性內插值是針對與分貝值相對應的振幅(最小值爲-80)。 db到amp轉換不是線性的(它是指數的)。放大器調整後的放大器轉換是線性插值。 – Geebs

+0

你好。再次感謝您的回覆。是的,我瞭解log v/s線性刻度,以及爲什麼繪製線性關係至關重要。我想確認的是「響應曲線」和調整,但似乎我很關注「var名稱的含義」。 > _ <。但是,再次感謝您的回覆。 :) – codeBearer