Python u-Law (MULAW) 波解压缩为原始波信号

Dan*_*ilo 5 python waveform pcm mu-law

我在过去两周内用谷歌搜索了这个问题,但未能找到算法或解决方案。我有一些短的 .wav 文件,但它有 MULAW 压缩,而 python 内部似乎没有wave.py可以成功解压缩它的函数。所以我自己用 python 构建了一个解码器。

\n\n

我在基本元素中找到了一些关于 MULAW 的信息:

\n\n
    \n
  1. 维基百科
  2. \n
  3. A 律 u 律比较
  4. \n
  5. 一些c-esc编解码器库
  6. \n
\n\n

所以我需要一些指导,因为我不知道如何从有符号短整数转换为全波信号。这是我迄今为止收集到的初步想法:

\n\n
\n\n

所以从 wiki 我得到了 u-law 压缩和解压缩的方程:

\n\n

压缩 : 压缩

\n\n

减压: 在此输入图像描述

\n\n

因此,从压缩方程来看,输出似乎限制在float-1 到 +1 的范围内,并且有符号短整数从 \xe2\x80\x9332,768 到 32,767 所以看起来我需要将其转换为short intfloat特定范围内。

\n\n

现在,说实话,我以前听说过量化,但我不确定是否应该首先尝试去量化然后解压缩或以其他方式,或者即使在这种情况下它是同一件事......教程/文档的术语可能有点棘手。

\n\n

我正在使用的波形文件应该包含“A”声音,就像语音合成一样,我可能可以通过比较某些音频软件和自定义波形分析器中的 2 个波形来验证成功,但我真的很想减少尝试和错误部分这个过程的。

\n\n

所以我的想法是:

\n\n
u = 0xff\ndata_chunk = b\'\\xe7\\xe7\' # -6169\ndata_to_r1 = unpack(\'h\',data_chunk)[0]/0xffff # I suspect this is wrong,\n#                                             # but I don\'t know what else\n\nu_law = ( -1 if data_chunk<0 else 1 )*( pow( 1+u, abs(data_to_r1)) -1 )/u   \n
Run Code Online (Sandbox Code Playgroud)\n\n

那么我需要采取某种算法或关键步骤吗?第一解压缩第二量化第三
\n因为我在 google 上找到的所有内容都是如何读取.wavPCM 调制的文件类型,而不是在出现狂野压缩时如何管理它。

\n

Dan*_*ilo 3

所以,在谷歌搜索后,在 github 中找到了解决方案(见图)。我搜索了很多算法,发现 1 种算法在有损压缩的误差范围内。对于 30 -> 1 的正值和 -32 -> -1 的负值来说,这适用于 u 定律

老实说,我认为这个解决方案是足够的,但不完全是每个方程,但它是目前最好的解决方案。此代码直接从gcc9108 音频编解码器转录为 python

def uLaw_d(i8bit):
    bias = 33
    sign = pos = 0
    decoded = 0

    i8bit = ~i8bit
    if i8bit&0x80:
        i8bit &= ~(1<<7)
        sign = -1

    pos = ( (i8bit&0xf0) >> 4 ) + 5
    decoded = ((1 << pos) | ((i8bit & 0x0F) << (pos - 4)) | (1 << (pos - 5))) - bias
    return decoded if sign else ~decoded

def uLaw_e(i16bit):
    MAX = 0x1fff
    BIAS = 33
    mask = 0x1000
    sign = lsb = 0
    pos = 12 

    if i16bit < 0:
        i16bit = -i16bit
        sign = 0x80

    i16bit += BIAS

    if ( i16bit>MAX ): i16bit = MAX 

    for x in reversed(range(pos)):
        if i16bit&mask != mask and pos>=5:
            pos = x
            break

    lsb = ( i16bit>>(pos-4) )&0xf
    return ( ~( sign | ( pos<<4 ) | lsb ) )
Run Code Online (Sandbox Code Playgroud)

通过测试:

print( 'normal :\t{0}\t|\t{0:2X}\t:\t{0:016b}'.format(0xff) )
print( 'encoded:\t{0}\t|\t{0:2X}\t:\t{0:016b}'.format(uLaw_e(0xff)) )
print( 'decoded:\t{0}\t|\t{0:2X}\t:\t{0:016b}'.format(uLaw_d(uLaw_e(0xff))) )
Run Code Online (Sandbox Code Playgroud)

和输出:

normal :    255     |   FF  :   0000000011111111
encoded:    -179    |   -B3 :   -000000010110011
decoded:    263     |   107 :   0000000100000111
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,263-255 = 8 在范围内。当我尝试实现G.711seeemmmm中描述的方法时,那位好心的用户 Oliver Charlesworth 建议我查看,数据中最大值的解码值为 -8036,接近 uLaw 规范的最大值,但我无法反转设计解码函数以获得维基百科函数的二进制等效项。

最后,我必须说,我目前对 python 库不支持所有类型的压缩算法感到失望,因为它不仅仅是人们使用的工具,它也是 python 消费者学习的资源,因为大多数数据都需要进一步深入研究代码不容易获得或难以理解。


编辑

在解码数据并通过写入 wav 文件后,wave.py我成功地成功写入了一个新的原始线性 PCM 文件。这很有效……尽管我一开始对此表示怀疑。


编辑2:::>你可以在compressions.py上找到真正的解决方案