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é)串對象 中。除非特別說明,否則所有標(biāo)量項目均為整數(shù)。

在 3.4 版更改: 增加了對 24 位采樣的支持?,F(xiàn)在,所有函數(shù)都接受任何 類字節(jié)串對象。而傳入字符串會立即導(dǎo)致錯誤。

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

部分更復(fù)雜的操作僅接受 16 位采樣,而其他操作始終需要采樣大?。ㄒ宰止?jié)為單位)作為該操作的參數(shù)。

此模塊定義了下列變量和函數(shù):

exception audioop.error?

所有錯誤都會拋出此異常,比如采樣值的字節(jié)數(shù)未知等等。

audioop.add(fragment1, fragment2, width)?

兩個采樣作為參數(shù)傳入,返回一個片段,該片段是兩個采樣的和。width 是采樣位寬(以字節(jié)為單位),可以取 1, 2, 34。兩個片段的長度應(yīng)相同。如果發(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 最匹配。兩個片段都應(yīng)包含 2 字節(jié)寬的采樣。

本例程所需的時間與 len(fragment) 成正比。

audioop.findfit(fragment, reference)?

盡可能嘗試讓 reference 匹配 fragment 的一部分(fragment 應(yīng)較長)。從概念上講,完成這些靠從 fragment 中取出切片,使用 findfactor() 計算最佳匹配,并最小化結(jié)果。兩個片段都應(yīng)包含 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]) 最大。兩個片段都應(yīng)包含 2 字節(jié)寬的采樣。

本例程所需的時間與 len(fragment) 成正比。

audioop.getsample(fragment, width, index)?

返回片段中采樣值索引 index 的值。

audioop.lin2adpcm(fragment, width, state)?

將采樣轉(zhuǎn)換為 4 位 Intel/DVI ADPCM 編碼。ADPCM 編碼是一種自適應(yīng)編碼方案,其中每個 4 比特數(shù)字是一個采樣值與下一個采樣值之間的差除以(不定的)步長。IMA 已選擇使用 Intel/DVI ADPCM 算法,因此它很可能成為標(biāo)準(zhǔn)。

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 位采樣是無符號的。因此,當(dāng)將這些格式轉(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)用應(yīng)傳入 None 作為 state。

參數(shù) weightAweightB 是簡單數(shù)字濾波器的參數(shù),默認(rèn)分別為 10。

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)問題,應(yīng)先將立體聲片段拆分為兩個單聲道片段,之后再重組。以下是如何進行該操作的示例:

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ù),還應(yīng)該傳輸狀態(tài)。請注意,必須將*初始*狀態(tài)(傳入 lin2adpcm() 的狀態(tài))發(fā)送給解碼器,不能發(fā)送最終狀態(tài)(編碼器返回的狀態(tài))。如果要使用 struct.Struct 以二進制保存狀態(tài),可以將第一個元素(預(yù)測值)用 16 位編碼,將第二個元素(增量索引)用 8 位編碼。

本 ADPCM 編碼器從不與其他 ADPCM 編碼器對立,僅針對自身。本開發(fā)者可能會誤讀標(biāo)準(zhǔn),這種情況下它們將無法與相應(yīng)標(biāo)準(zhǔn)互操作。

乍看之下 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)