[英]Is it correct to assume that floating-point samples in a WAV or AIFF file will be normalized?
假設我有一個讀取.WAV或.AIFF文件的程序,文件的音頻被編碼為浮點樣本值。 我的程序假設任何格式良好(基於浮點的).WAV或.AIFF文件只包含[-1.0f,+ 1.0f]范圍內的樣本值是否正確? 我找不到解決這一點的WAV或AIFF規范中的任何內容。
如果這不是一個有效的假設,那么如何才能知道文件中音頻的完整動態范圍是什么? (我可以讀取整個文件並找出文件的實際最小和最大樣本值是什么,但是有兩個問題:(1)如果文件非常大,那將是一個緩慢/昂貴的操作,(2) )它會丟失信息,因為如果文件的創建者打算讓文件有一些“余量”,以免在dbFS最大點播放,我的程序將無法檢測到這一點)
正如您所述,公共可用文檔不會詳細介紹浮點使用的范圍。 但是,根據過去幾年的行業實踐,以及作為浮點文件存在的實際數據,我認為這是一個有效的假設。
這有實際的原因,以及高精度數據標准化的常見范圍,如顏色,音頻,3D等。
范圍在區間[-1,1]中的主要原因是它快速且易於縮放/轉換為目標位范圍。 您只需提供目標范圍並乘以。
例如:
如果你想以16位的速度播放你會做(偽,假設有符號舍入為整數結果):
sample = in < 0 ? in * 0x8000 : in * 0x7fff;
或24位:
sample = in < 0 ? in * 0x800000 : in * 0x7fffff;
或8位:
sample = in < 0 ? in * 0x80 : in * 0x7f;
等,無需以任何方式調整原始輸入值。 -1和1表示轉換為目標時的最小/最大值(1x = x)。
如果您使用[-0.5,0.5]的范圍,您將首先(或在某些時候)必須調整輸入值,因此轉換為例如16位需要額外的步驟 - 這需要額外的成本,不僅僅是額外的步驟,但也因為我們將在浮點域工作,這是一個更重要的計算(后者可能有點遺留的原因,因為浮點處理現在非常快,但無論如何)。
in = in * 2;
sample = in < 0 ? in * 0x8000 : in * 0x7fff;
將其保持在[-1,1]范圍而不是某些預先縮放的范圍(例如[-32768,32767])也允許使用更多位來實現精度(使用IEEE 754表示)。
更新2017/07
根據評論中的問題,我決定使用三個帶有1秒正弦波的文件進行三重檢查:
A)浮點剪裁
B)浮點最大0dB,和
C)整數削減(從A轉換)
然后在data
塊和大小字段之后開始掃描正值<= -1.0和> = 1.0的文件,以使得最小值/最大值反映在音頻數據中找到的實際值。
結果證實,當不進行削波時,該范圍確實在[-1,1]包含范圍內(非真實<= 0 dB)。
但它也揭示了另一個方面 -
保存為浮點確實允許超過0 dB的范圍值WAV文件。 這意味着對於通常會剪切的值,范圍實際上超出[-1,1]。
對此的解釋可能是浮點格式旨在用於生產設置中的中間使用,因為動態范圍的損失非常小,未來的處理(增益分段,壓縮,限制等)可以帶回值(無損失)在最終和正常-0.2 - 0 dB范圍內; 因此保留了原樣。
使用浮點的WAV文件將在不剪切(<= 0dB)時保存[-1,1]中的值,但允許被視為剪切的值
但是當轉換為整數格式時,這些值將剪切到等於整數格式的位范圍的等效[-1,1]范圍,無論如何。 這是自然的,因為每個寬度可以容納的范圍有限。
因此,通過標准化數據或簡單地剪回[-1,1],可以使播放器/ DAW /編輯軟件處理剪切的浮點值。
注意:所有文件的最大值都是直接從樣本數據中測量的。
注意:產生剪切浮點數(+ 6 dB),然后轉換為帶符號的16位並返回浮點數
注意:削減到+6 dB
注意:剪切為+12 dB
可在此處找到簡單的測試腳本和文件。
我知道問題不是特定於給定的編程語言或框架,但我在任何規范中都找不到答案。 我可以肯定地說,廣泛用於處理為.NET框架編寫的應用程序中的.WAV文件的NAudio庫假定浮動樣本在[-1.0,+ 1.0]范圍內。
namespace NAudio.Wave
{
public class WaveFileReader : WaveStream
{
...
/// <summary>
/// Attempts to read the next sample or group of samples as floating point normalised into the range -1.0f to 1.0f
/// </summary>
/// <returns>An array of samples, 1 for mono, 2 for stereo etc. Null indicates end of file reached
/// </returns>
public float[] ReadNextSampleFrame()
{
...
var sampleFrame = new float[waveFormat.Channels];
int bytesToRead = waveFormat.Channels*(waveFormat.BitsPerSample/8);
...
for (int channel = 0; channel < waveFormat.Channels; channel++)
{
if (waveFormat.BitsPerSample == 16)
...
else if (waveFormat.BitsPerSample == 32 && waveFormat.Encoding == WaveFormatEncoding.IeeeFloat)
{
sampleFrame[channel] = BitConverter.ToSingle(raw, offset);
offset += 4;
}
...
}
return sampleFrame;
}
...
}
}
因此,它只是將float復制到數組中而不對其進行任何轉換,並保證它在給定范圍內。
是。
音頻文件格式充當一個或多個音頻數據通道的載體。 該音頻數據已使用特定的音頻編碼格式進行編碼 。 每種編碼格式使用編碼器算法 。 算法是重要的部分。 我們可以手動擺脫文件和編碼格式的價值。
AIFF和WAV都使用脈沖編碼調制(PCM)或其后代。 (如果您查看此Oracle文檔 ,您會注意到在“Encoding / CompressionType”基於PCM的算法列表下。)PCM通過以固定的時間間隔對音頻正弦波進行采樣並選擇最近的數字表示來工作。 這里重要的是“正弦波”。
正弦波在-1和1之間調制,因此所有PCM衍生編碼將根據該原理運行。 考慮mu-law實現:在其定義等式中注意,范圍必須為-1到1。
我正在做很多動手,簡單地回答這個問題。 有時我們必須騙孩子 。 如果你想更深入地研究浮點與定點,比特深度對錯誤的重要性等,請查閱一本關於DSP的好書。 為了幫助您入門:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.