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)