2015-09-09 41 views
0

我有一個波形文件(PCM)。 我已經刪除了標題並將音頻數據讀取到一個字節數組中。秒到音頻文件中的字節位置

我想找出給定時間值的字節位置(例如6,72911493013085E-02秒)。

我寫了一個轉換器功能:

Public Function SecondsToBytePos(ByVal uSeconds As Double, ByVal uSamplesPerSecond As Long, ByVal uChannels As Long, ByVal uBitsPerSample) As Long 

    Dim lRet& 
    lRet = (uSeconds * ((uSamplesPerSecond * uChannels * uBitsPerSample)/8)) 

    SecondsToBytePos = lRet 

End Function 

然而,當我使用

SecondsToBytePos(6,72911493013085E-02,48000,1,16)

我得到的偶數值6460

這是不正確的,因爲字節數組是從零開始的,所以這個值需要是奇數。

2個字節組成1個double/float值,所以偶數值永遠不會發生。

有沒有人在我的轉換器功能中看到任何缺陷?

謝謝你的幫助。

編輯:這是一種不同的方法:

Public Function SecondsToBytePos(ByVal uSeconds As Double, ByVal uSamplesPerSecond As Long, ByVal uChannels As Long, ByVal uBitsPerSample) As Long 

    Dim g_lBlockAlign As Long=2 

    Dim lret& 
    lret = (uSeconds * ((uSamplesPerSecond * uChannels * uBitsPerSample)/8)) 

    If (lret Mod g_lBlockAlign) > 0 Then 
     Dim lRem& 
     lRem = (lret \ g_lBlockAlign) + 1 
     lret = lRem * g_lBlockAlign 
    End If 

    SecondsToBytePos = lret 

End Function 

回答

0

你的假設,即返回值必須是奇數是錯誤的 - 因爲你轉換爲字節,而不是樣品或幀。

如果希望第一信道的第一樣本的字節位置開始在時間uSeconds:

frameNumber = Floor(uSeconds * uSamplesPerSecond) 
bytePos = frameNumber * numChannels * bitsPerSample/8 

bytePos將numChannels * bitsPerSample/8

如果希望字節的倍數的的第一樣本的位置的任何通道起始於時間uSeconds:

sampleNumber = Floor(uSeconds * uSamplesPerSecond * numChannels) 
bytePos = sampleNumber * bitsPerSample/8 

這裏bytePos將多倍bitsPerSample/8

我會懷疑你想要frameNumber,因爲它與你的數據對齊 - 如果你想從該位置回放,例如你的左和右將留在左側和右側。

+0

該文件是單聲道的。樣本是1個雙/平面值,即2個字節。你仍然認爲我的假設是錯誤的嗎? – MaikenRosk

+0

是的,它適用於所有情況。考慮一個簡單的例子。 1秒48kHz音頻,單聲道,16位。您首先轉換爲96000字節的數量。然後,您使用秒來索引該數字。如果你在0.5秒時要求字節,那麼你將得到48000.如果你要求在(0.5 +(1/48000.0))處的字節,你將得到48001.我的答案的要點是,你需要保留在索引之前構建你的願望,然後*將該答案轉換爲字節。 – jaket

+0

我不信任「樓層」。我在帖子中增加了另一種方法。我也可以使用這種BlockAlign方法嗎? – MaikenRosk