audioop
--- 處理原始音頻數(shù)據(jù)?
Deprecated since version 3.11, will be removed in version 3.13: The audioop
module is deprecated
(see PEP 594 for details).
audioop
模塊包含針對聲音片段的一些有用操作。它操作的聲音片段由 8、16、24 或 32 位寬的有符號整型采樣值組成,存儲在 類字節(jié)串對象 中。除非特別說明,否則所有標量項目均為整數(shù)。
在 3.4 版更改: 增加了對 24 位采樣的支持?,F(xiàn)在,所有函數(shù)都接受任何 類字節(jié)串對象。而傳入字符串會立即導致錯誤。
本模塊提供對 a-LAW、u-LAW 和 Intel/DVI ADPCM 編碼的支持。
部分更復雜的操作僅接受 16 位采樣,而其他操作始終需要采樣大?。ㄒ宰止?jié)為單位)作為該操作的參數(shù)。
此模塊定義了下列變量和函數(shù):
- exception audioop.error?
所有錯誤都會拋出此異常,比如采樣值的字節(jié)數(shù)未知等等。
- audioop.add(fragment1, fragment2, width)?
兩個采樣作為參數(shù)傳入,返回一個片段,該片段是兩個采樣的和。width 是采樣位寬(以字節(jié)為單位),可以取
1
,2
,3
或4
。兩個片段的長度應相同。如果發(fā)生溢出,較長的采樣將被截斷。
- audioop.adpcm2lin(adpcmfragment, width, state)?
將 Intel/DVI ADPCM 編碼的片段解碼為線性片段。關(guān)于 ADPCM 編碼的詳情請參閱
lin2adpcm()
的描述。返回一個元組(sample, newstate)
,其中 sample 的位寬由 width 指定。
- audioop.alaw2lin(fragment, width)?
將 a-LAW 編碼的聲音片段轉(zhuǎn)換為線性編碼聲音片段。由于 a-LAW 編碼采樣值始終為 8 位,因此這里的 width 僅指輸出片段的采樣位寬。
- audioop.avg(fragment, width)?
返回片段中所有采樣值的平均值。
- audioop.avgpp(fragment, width)?
返回片段中所有采樣值的平均峰峰值。由于沒有進行過濾,因此該例程的實用性尚存疑。
- audioop.bias(fragment, width, bias)?
返回一個片段,該片段由原始片段中的每個采樣值加上偏差組成。在溢出時采樣值會回卷 (wrap around)。
- audioop.byteswap(fragment, width)?
“按字節(jié)交換”片段中的所有采樣值,返回修改后的片段。將大端序采樣轉(zhuǎn)換為小端序采樣,反之亦然。
3.4 新版功能.
- audioop.cross(fragment, width)?
將片段作為參數(shù)傳入,返回其中過零點的數(shù)量。
- audioop.findfactor(fragment, reference)?
返回一個系數(shù) F 使得
rms(add(fragment, mul(reference, -F)))
最小,即返回的系數(shù)乘以 reference 后與 fragment 最匹配。兩個片段都應包含 2 字節(jié)寬的采樣。本例程所需的時間與
len(fragment)
成正比。
- audioop.findfit(fragment, reference)?
盡可能嘗試讓 reference 匹配 fragment 的一部分(fragment 應較長)。從概念上講,完成這些靠從 fragment 中取出切片,使用
findfactor()
計算最佳匹配,并最小化結(jié)果。兩個片段都應包含 2 字節(jié)寬的采樣。返回一個元組(offset, factor)
,其中 offset 是在 fragment 中的偏移量(整數(shù)),表示從此處開始最佳匹配,而 factor 是由findfactor()
定義的因數(shù)(浮點數(shù))。
- audioop.findmax(fragment, length)?
在 fragment 中搜索所有長度為 length 的采樣切片(不是字節(jié)?。┲校芰孔畲蟮哪且粋€切片,即返回 i 使得
rms(fragment[i*2:(i+length)*2])
最大。兩個片段都應包含 2 字節(jié)寬的采樣。本例程所需的時間與
len(fragment)
成正比。
- audioop.getsample(fragment, width, index)?
返回片段中采樣值索引 index 的值。
- audioop.lin2adpcm(fragment, width, state)?
將采樣轉(zhuǎn)換為 4 位 Intel/DVI ADPCM 編碼。ADPCM 編碼是一種自適應編碼方案,其中每個 4 比特數(shù)字是一個采樣值與下一個采樣值之間的差除以(不定的)步長。IMA 已選擇使用 Intel/DVI ADPCM 算法,因此它很可能成為標準。
state 是一個表示編碼器狀態(tài)的元組。編碼器返回一個元組
(adpcmfrag, newstate)
,而 newstate 要在下一次調(diào)用lin2adpcm()
時傳入。在初始調(diào)用中,可以將None
作為 state 傳遞。adpcmfrag 是 ADPCM 編碼的片段,每個字節(jié)打包了 2 個 4 比特值。
- audioop.lin2alaw(fragment, width)?
將音頻片段中的采樣值轉(zhuǎn)換為 a-LAW 編碼,并將其作為字節(jié)對象返回。a-LAW 是一種音頻編碼格式,僅使用 8 位采樣即可獲得大約 13 位的動態(tài)范圍。Sun 音頻硬件等使用該編碼。
- audioop.lin2lin(fragment, width, newwidth)?
將采樣在 1、2、3 和 4 字節(jié)格式之間轉(zhuǎn)換。
備注
在某些音頻格式(如 .WAV 文件)中,16、24 和 32 位采樣是有符號的,但 8 位采樣是無符號的。因此,當將這些格式轉(zhuǎn)換為 8 位寬采樣時,還需使結(jié)果加上 128:
new_frames = audioop.lin2lin(frames, old_width, 1) new_frames = audioop.bias(new_frames, 1, 128)
反之,將 8 位寬的采樣轉(zhuǎn)換為 16、24 或 32 位時,必須采用相同的處理。
- audioop.lin2ulaw(fragment, width)?
將音頻片段中的采樣值轉(zhuǎn)換為 u-LAW 編碼,并將其作為字節(jié)對象返回。u-LAW 是一種音頻編碼格式,僅使用 8 位采樣即可獲得大約 14 位的動態(tài)范圍。Sun 音頻硬件等使用該編碼。
- audioop.max(fragment, width)?
返回片段中所有采樣值的最大 絕對值。
- audioop.maxpp(fragment, width)?
返回聲音片段中的最大峰峰值。
- audioop.minmax(fragment, width)?
返回聲音片段中所有采樣值的最小值和最大值組成的元組。
- audioop.mul(fragment, width, factor)?
返回一個片段,該片段由原始片段中的每個采樣值乘以浮點值 factor 組成。如果發(fā)生溢出,采樣將被截斷。
- audioop.ratecv(fragment, width, nchannels, inrate, outrate, state[, weightA[, weightB]])?
轉(zhuǎn)換輸入片段的幀速率。
state 是一個表示轉(zhuǎn)換器狀態(tài)的元組。轉(zhuǎn)換器返回一個元組
(newfragment, newstate)
,而 newstate 要在下一次調(diào)用ratecv()
時傳入。初始調(diào)用應傳入None
作為 state。參數(shù) weightA 和 weightB 是簡單數(shù)字濾波器的參數(shù),默認分別為
1
和0
。
- audioop.reverse(fragment, width)?
將片段中的采樣值反轉(zhuǎn),返回修改后的片段。
- audioop.rms(fragment, width)?
返回片段的均方根值,即
sqrt(sum(S_i^2)/n)
。測量音頻信號的能量。
- audioop.tomono(fragment, width, lfactor, rfactor)?
將立體聲片段轉(zhuǎn)換為單聲道片段。左通道乘以 lfactor,右通道乘以 rfactor,然后兩個通道相加得到單聲道信號。
- audioop.tostereo(fragment, width, lfactor, rfactor)?
由單聲道片段生成立體聲片段。立體聲片段中的兩對采樣都是從單聲道計算而來的,即左聲道是乘以 lfactor,右聲道是乘以 rfactor。
- audioop.ulaw2lin(fragment, width)?
將 u-LAW 編碼的聲音片段轉(zhuǎn)換為線性編碼聲音片段。由于 u-LAW 編碼采樣值始終為 8 位,因此這里的 width 僅指輸出片段的采樣位寬。
請注意,諸如 mul()
或 max()
之類的操作在單聲道和立體聲間沒有區(qū)別,即所有采樣都作相同處理。如果出現(xiàn)問題,應先將立體聲片段拆分為兩個單聲道片段,之后再重組。以下是如何進行該操作的示例:
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 編碼器構(gòu)造網(wǎng)絡(luò)數(shù)據(jù)包,并且希望協(xié)議是無狀態(tài)的(即能夠容忍數(shù)據(jù)包丟失),則不僅需要傳輸數(shù)據(jù),還應該傳輸狀態(tài)。請注意,必須將*初始*狀態(tài)(傳入 lin2adpcm()
的狀態(tài))發(fā)送給解碼器,不能發(fā)送最終狀態(tài)(編碼器返回的狀態(tài))。如果要使用 struct.Struct
以二進制保存狀態(tài),可以將第一個元素(預測值)用 16 位編碼,將第二個元素(增量索引)用 8 位編碼。
本 ADPCM 編碼器從不與其他 ADPCM 編碼器對立,僅針對自身。本開發(fā)者可能會誤讀標準,這種情況下它們將無法與相應標準互操作。
乍看之下 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)