【问题标题】:Python u-Law (MULAW) wave decompression to raw wave signalPython u-Law (MULAW) 波解压为原始波信号
【发布时间】:2018-04-29 10:48:12
【问题描述】:

我在过去 2 周内搜索了这个问题,但找不到算法或解决方案。我有一些简短的 .wav 文件,但它具有 MULAW 压缩,并且 python 在 wave.py 中似乎没有可以成功解压缩它的功能。所以我开始自己用python构建一个解码器。

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

  1. Wikipedia
  2. A-law u-Law comparison
  3. Some c-esc codec library

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


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

压缩:

解压:

所以从压缩方程来看,看起来输出被限制在 -1 到 +1 的 float 范围内,并且带有从 –32,768 到 32,767 的有符号短整数,所以看起来我需要将它从short intfloat 在特定范围内。

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

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

所以我的想法是:

u = 0xff
data_chunk = b'\xe7\xe7' # -6169
data_to_r1 = unpack('h',data_chunk)[0]/0xffff # I suspect this is wrong,
#                                             # but I don't know what else

u_law = ( -1 if data_chunk<0 else 1 )*( pow( 1+u, abs(data_to_r1)) -1 )/u   

那么,我是否需要采取某种算法或关键步骤,形式为 first: decompression, second: 量化 : 第三 ?
由于我在谷歌上找到的所有内容都是如何读取.wav PCM 调制的文件类型,而不是在出现野压缩时如何管理它。

【问题讨论】:

  • 查看G.711,了解基于此的编解码器的实际示例。
  • 什么是lseg、linbuf、logbuf?

标签: python pcm waveform mu-law


【解决方案1】:

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

说实话,我认为这个解决方案是足够的,但不是完全按照方程式说的,但它是目前最好的解决方案。这段代码直接从gcc9108 audio codec转录成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 ) )

有测试:

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))) )

和输出:

normal :    255     |   FF  :   0000000011111111
encoded:    -179    |   -B3 :   -000000010110011
decoded:    263     |   107 :   0000000100000111

如您所见,263-255 = 8 在界限内。当我尝试实现G.711 中描述的seeemmmm 方法时,那种用户Oliver Charlesworth 建议我查看,数据中最大值的解码值为-8036,接近uLaw 规范的最大值,但我不能't 逆向工程解码函数以从维基百科获取函数的二进制等效项。

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


编辑

解码数据并通过wave.py 写入wav 文件后,我成功地写入了一个新的原始线性PCM 文件。这行得通……尽管我一开始持怀疑态度。


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


【讨论】:

    【解决方案2】:

    我发现这对于使用 numpy 数组与 ulaw 相互转换很有帮助。

    import audioop
    
    def numpy_audioop_helper(x, xdtype, func, width, ydtype):
        '''helper function for using audioop buffer conversion in numpy'''
        xi = np.asanyarray(x).astype(xdtype)
        if np.any(x != xi):
            xinfo = np.iinfo(xdtype)
            raise ValueError("input must be %s [%d..%d]" % (xdtype, xinfo.min, xinfo.max))
        y = np.frombuffer(func(xi.tobytes(), width), dtype=ydtype)
        return y.reshape(xi.shape)
    
    def audioop_ulaw_compress(x):
        return numpy_audioop_helper(x, np.int16, audioop.lin2ulaw, 2, np.uint8)
    
    def audioop_ulaw_expand(x):
        return numpy_audioop_helper(x, np.uint8, audioop.ulaw2lin, 2, np.int16)
    

    【讨论】:

    • 说实话。从未使用过 numpy 或 pycharm 或任何扩展 python 的东西。我需要这样做的原因不是转换或数据处理。它是 mp3/wav 压缩(除其他外)标志识别。 Python 有一些带有有限标志的错误,如果文件是用通用、标准和广泛使用的标志编写的,python 加载它没有问题,但如果文件是用其他标志编写的,则会引发错误......所以你需要阅读二进制文件然后自己构造和解压ulaw。
    【解决方案3】:

    Python 实际上支持开箱即用地解码 u-Law:

    audioop.ulaw2lin(fragment, width)

    将 u-LAW 编码中的声音片段转换为线性编码的声音片段。 u-LAW 编码始终使用 8 位样本,因此宽度 此处仅指输出片段的样本宽度。

    https://docs.python.org/3/library/audioop.html#audioop.ulaw2lin

    【讨论】:

    • 它可以,但前提是您要读取的文件具有简单的压缩标志。我得到了带有 mulaw 压缩标志的 mp3 文件,但 python 无法识别它。所以它并不适用于所有事情。
    猜你喜欢
    • 1970-01-01
    • 2018-10-26
    • 2021-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-02
    • 2013-08-07
    • 2018-11-28
    相关资源
    最近更新 更多