首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python Law (MULAW)波解压为原始波信号

Python Law (MULAW)波解压为原始波信号
EN

Stack Overflow用户
提问于 2018-04-29 10:48:12
回答 3查看 8K关注 0票数 4

在过去的两周里,我一直在谷歌上搜索这个问题,却找不到算法或解决方案。我有一些简短的.wav文件,但是它有MULAW压缩,而且python在wave.py中似乎没有能够成功解压它的功能。所以我已经开始在python中构建一个解码器。

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

  1. 维基百科
  2. A-法u-律比较
  3. 一些c-esc编解码器库

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

所以从wiki我得到了u定律压缩和解压缩的方程式:

压缩:

减压:

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

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

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

所以我的想法是:

代码语言:javascript
复制
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   

那么,是否有某种算法或关键步骤,我需要采取的形式是第一:解压缩,第二:量化:第三

因为我在google上找到的所有东西都是如何读取.wav PCM调制的文件类型,而不是在出现疯狂压缩时如何管理它。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-05-02 14:24:41

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

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

代码语言:javascript
复制
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 ) )

经试验:

代码语言:javascript
复制
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))) )

和产出:

代码语言:javascript
复制
normal :    255     |   FF  :   0000000011111111
encoded:    -179    |   -B3 :   -000000010110011
decoded:    263     |   107 :   0000000100000111

正如您所看到的,263-255 =8,这是在范围内。当我试图实现用seeemmmm描述的G.711方法时,用户Oliver建议我查看一下,数据中最大值的解码值是-8036,接近uLaw规范的最大值,但我无法从维基百科反向工程解码函数以获得二进制等效的功能。

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

编辑

在解码数据并通过wave.py编写wav文件之后,我成功地编写了一个新的原始线性PCM文件。这很管用..。尽管一开始我很怀疑。

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

票数 3
EN

Stack Overflow用户

发布于 2019-07-09 20:26:47

我发现这对于使用numpy数组转换/从ulaw转换很有帮助。

代码语言:javascript
复制
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)
票数 3
EN

Stack Overflow用户

发布于 2018-07-31 06:56:04

Python实际上支持从盒子里解码u-Law:

audioop.ulaw2lin(fragment, width) 将u律编码中的声音片段转换为线性编码的声音片段。U律编码总是使用8位样本,因此宽度仅指输出片段的样本宽度。

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50085735

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档