python3從零學習-5.11.1、 audioop—操作原始音頻數據

 

audioop模塊包含一些對聲音片段的有用操作。它對聲音片段進行操作,這些聲音片段由8、16、24或32位寬的帶符號整數樣本組成,存儲在類似字節的對象中。除非另有指定,否則所有標量項都是整數。

 

在3.4版更改:支持24位樣品了。所有函數現在都接受任何字節類對象。字符串輸入現在會立即導致錯誤。

 

本模塊支持a-LAW、u-LAW和Intel/DVI ADPCM編碼。

 

一些更復雜的操作只使用16位樣本,否則樣本大小(以字節爲單位)始終是操作的一個參數。

 

模塊定義了以下變量和函數:

exception audioop.error

這個異常會在所有錯誤上引發,比如每個樣本的未知字節數,等等。

 

audioop.add(fragment1, fragment2, width)

返回一個片段,它是作爲參數傳遞的兩個樣本的附加。寬度是以字節爲單位的採樣寬度,可以是1、2、3或4。兩個片段應該具有相同的長度。樣本被截斷以防溢出。

 

audioop.adpcm2lin(adpcmfragment, width, state)

解碼一個英特爾/DVI ADPCM編碼片段到一個線性片段。有關ADPCM編碼的詳細信息,請參閱lin2adpcm()的描述。返回一個元組(sample, newstate),其中示例的寬度在width中指定。

 

audioop.alaw2lin(fragment, width)

在a-LAW編碼轉換聲音片段到線性編碼的聲音片段。a-LAW編碼總是使用8位樣本,因此寬度僅指輸出片段的樣本寬度。

 

audioop.avg(fragment, width)

返回片段中所有樣本的平均值。

 

audioop.avgpp(fragment, width)

返回片段中所有樣本的平均峯值。沒有進行過濾,因此這個例程的有用性值得懷疑。

 

audioop.bias(fragment, width, bias)

返回一個片段,該片段是原始片段,並在每個樣本中添加偏差。樣品被包裹起來以防溢出。

 

audioop.byteswap(fragment, width)

“Byteswap”將所有樣本放在一個片段中,並返回修改後的片段。將big-endian示例轉換爲little-endian示例,反之亦然。

 

audioop.cross(fragment, width)

返回作爲參數傳遞的片段中的零交叉次數。

 

audioop.findfactor(fragment, reference)

返回一個因子F,使rms(添加(片段,mul(引用,-F))最小,即,返回應該與之相乘的引用以使其儘可能與fragment匹配的因子。這些片段都應該包含2字節的示例。

 

這個例程所花費的時間與len(fragment)成比例。

 

audioop.findfit(fragment, reference)

儘量將引用匹配到片段的一部分(應該是較長的片段)。這(從概念上)是通過從片段中取出切片、使用findfactor()計算最佳匹配並最小化結果來完成的。這些片段都應該包含2字節的示例。返回一個元組(偏移量、因子),其中偏移量是最優匹配開始的片段中的(整數)偏移量,而因子是findfactor()中的(浮點)因子。

 

audioop.findmax(fragment, length)

搜索片段,以獲得最大能量的片段長度樣本(不是字節!),返回rms(fragment[i*2:(i+length)*2])的最大值。這些片段都應該包含2字節的示例。

例程花費的時間與len(fragment)成比例。

 

audioop.getsample(fragment, width, index)

從片段中返回樣本索引的值。

 

audioop.lin2adpcm(fragment, width, state)

轉換樣本4位英特爾/DVI ADPCM編碼。ADPCM編碼是一種自適應編碼方案,其中每個4位數是一個樣本和下一個之間的差,除以一個(變化的)步驟。IMA選擇了Intel/DVI ADPCM算法,很有可能成爲標準。

 

state是包含編碼器狀態的元組。編碼器返回一個元組(adpcmfrag, newstate), newstate應該被傳遞給lin2adpcm()的下一個調用。在初始調用中,任何狀態都不能作爲狀態傳遞。adpcmfrag是ADPCM編碼片段,每字節封裝2個4位值。

 

audioop.lin2alaw(fragment, width)

將音頻片段中的樣本轉換爲a- law編碼並將其作爲字節對象返回。a- law是一種音頻編碼格式,你得到一個動態範圍約13位使用僅8位樣本。它被Sun音頻硬件所使用。

 

audioop.lin2lin(fragment, width, newwidth)

在1字節、2字節、3字節和4字節格式之間轉換示例。

註解在某些音頻格式,如wav文件,16日24和32位樣品簽署,但8位樣本是無符號的。所以當轉換爲8位寬的樣本爲這些格式,你也需要增加128的結果:

new_frames = audioop。lin2lin(幀old_width 1)

new_frames = audioop。偏見(new_frames, 128)

同樣的,反過來,必須應用從8位到16位、24位或32位寬度樣本的轉換。

audioop.lin2ulaw(fragment, width)

將音頻片段中的樣本轉換爲u-LAW編碼並將其作爲字節對象返回。u-LAW是一種音頻編碼格式,你得到一個動態範圍約14位使用僅8位樣本。它被Sun音頻硬件所使用。

 

audioop.max(fragment, width)

返回片段中所有樣本絕對值的最大值。

 

audioop.maxpp(fragment, width)

返回聲音片段中的最大峯值。

 

audioop.minmax(fragment, width)

返回一個元組,包含聲音片段中所有樣本的最小值和最大值。

 

audioop.mul(fragment, width, factor)

返回一個片段,該片段將原始片段中的所有樣本乘以浮點值因子。樣本被截斷以防溢出。

 

audioop.ratecv(fragment, width, nchannels, inrate, outrate, state[, weightA[, weightB]])

轉換輸入片段的幀速率。

 

state是包含轉換器狀態的元組。轉換器返回一個元組(newfragment, newstate), newstate應該被傳遞給ratecv()的下一個調用。初始調用應該將None作爲狀態傳遞。

 

weightA和weightB參數是一個簡單數字過濾器的參數,默認值分別爲1和0。

 

audioop.reverse(fragment, width)

將樣本反向到一個片段中,並返回修改後的片段。

 

audioop.rms(fragment, width)

返回片段的均方根,即sqrt(sum(S_i^2)/n)。

 

這是對音頻信號功率的測量。

 

audioop.tomono(fragment, width, lfactor, rfactor)

將立體片段轉換爲單聲道片段。左邊通道乘以lfactor,右邊通道乘以rfactor,然後將這兩個通道相加得到單聲道信號。

 

audioop.tostereo(fragment, width, lfactor, rfactor)

從單聲道片段生成立體片段。立體片段中的每對樣本由單聲道樣本計算,即左通道樣本乘以lfactor,右通道樣本乘以rfactor。

 

audioop.ulaw2lin(fragment, width)

轉換的聲音片段在u律編碼到線性編碼的聲音片段。u-LAW編碼總是使用8位樣本,因此寬度僅指輸出片段的樣本寬度。

 

注意,像mul()或max()這樣的操作在單聲道和立體片段之間沒有區別,也就是說,所有的樣本都被同等對待。如果這是一個問題,立體聲片段應該首先分裂成兩個單聲道片段,然後重新組合。下面是一個如何做到這一點的例子:

def mul_stereo(sample, width, lfactor, rfactor):
    lsample = audioop.tomono(sample, width, 1, 0)
    rsample = audioop.tomono(sample, width, 0, 1)
    lsample = audioop.mul(lsample, width, lfactor)
    rsample = audioop.mul(rsample, width, rfactor)
    lsample = audioop.tostereo(lsample, width, 1, 0)
    rsample = audioop.tostereo(rsample, width, 0, 1)
    return audioop.add(lsample, rsample, width)

如果你使用ADPCM編碼器來構建網絡數據包,並且你希望你的協議是無狀態的(即能夠容忍數據包丟失),你不僅應該傳輸數據,而且還應該傳輸狀態。注意,應該將初始狀態(傳遞給lin2adpcm()的狀態)發送到解碼器,而不是最終狀態(由編碼器返回)。如果你想使用struct。爲了將狀態存儲爲二進制,可以將第一個元素(預測值)編碼爲16位,將第二個元素(增量索引)編碼爲8位。

 

ADPCM編碼人員從未嘗試過對抗其他ADPCM編碼人員,只是對抗他們自己。很有可能是我誤解了標準,在這種情況下,它們將無法與各自的標準互操作。

 

乍一看,find*()例程可能有點滑稽。它們主要用於執行回顯消除。一種比較快速的方法是選取輸出樣本中精力最充沛的部分,定位到輸入樣本中,然後從輸入樣本中減去整個輸出樣本:

def echocancel(outputdata, inputdata):
    pos = audioop.findmax(outputdata, 800)    # one tenth second
    out_test = outputdata[pos*2:]
    in_test = inputdata[pos*2:]
    ipos, factor = audioop.findfit(in_test, out_test)
    # Optional (for better cancellation):
    # factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)],
    #              out_test)
    prefill = '\0'*(pos+ipos)*2
    postfill = '\0'*(len(inputdata)-len(prefill)-len(outputdata))
    outputdata = prefill + audioop.mul(outputdata, 2, -factor) + postfill
    return audioop.add(inputdata, outputdata, 2)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章