简体   繁体   English

使用python处理音频流(重采样)

[英]processing an audio stream with python (resampling)

I have a python script that receives chunks of binary raw audio data and I would like to change the sample rate of those chunks to 16000 and then pipe them to another component. 我有一个python脚本,可以接收二进制原始音频数据的块,我想将这些块的采样率更改为16000,然后将它们通过管道传输到另一个组件。

I tried my luck with audiotools but without success: 我尝试了Audiotools的运气,但没有成功:

# f is a filelike FIFO buffer
reader = PCMFileReader(f, 44100, 1, 1, 16)
conv = PCMConverter(reader, 16000, 1, 1, 16)

Then I just write to the buffer anytime, I get a new chunk: 然后,我随时可以写入缓冲区,得到一个新块:

f.write(msg)

And read from the buffer in another thread: 并从另一个线程的缓冲区中读取:

while not reader.file.closed:
    fl = conf.read(10)
    chunk = fl.to_bytes(False, True)

The problem is that I get this value error, which seems to come from a "samplerate.c" library: 问题是我得到了这个值错误,它似乎来自“ samplerate.c”库:

ValueError: SRC_DATA->data_out is NULL

This error only occurs with resampling. 仅在重新采样时才会发生此错误。 If I turn off that step, then everything works fine and I get playable audio. 如果我关闭该步骤,则一切正常,并且可以播放音频。

Therefore my question: What would be a good tool for this task? 因此,我的问题是:什么是完成此任务的好工具? And if audiotools turns out to be the right answer, how do I do that correctly. 如果audiotools确实是正确的答案,那么我该如何正确地做到这一点。

here is a simplified resampler code 这是简化的重采样器代码

dataFormat is a number of bytes per sample in the stream, ex: stereo 16 bit would be = 4, original_samples is a source bin string size, desired_samples is a desired bit string size, 16KHz->44K1Hz ex: original = 160 but desired = 441, pcm is a source bin string, return is resampled bin string) : dataFormat是流中每个样本的字节数,例如:立体声16位将为= 4, original_samples是源bin字符串大小, desired_samples是所需的位字符串大小,16KHz-> 44K1Hz例如:原始= 160,但期望= 441, pcm是源bin字符串,返回是重新采样的bin字符串):

def resampleSimplified(pcm, desired_samples, original_samples, dataFormat):

    samples_to_pad = desired_samples - original_samples

    q, r = divmod(desired_samples, original_samples)
    times_to_pad_up = q + int(bool(r))
    times_to_pad_down = q

    pcmList = [pcm[i:i+dataFormat] for i in range(0, len(pcm), dataFormat)]

    if samples_to_pad > 0:
        # extending pcm times_to_pad times
        pcmListPadded = list(itertools.chain.from_iterable(
            itertools.repeat(x, times_to_pad_up) for x in pcmList)
            )
    else:
        # shrinking pcm times_to_pad times
        if times_to_pad_down > 0:
            pcmListPadded = pcmList[::(times_to_pad_down)]
        else:
            pcmListPadded = pcmList

    padded_pcm = ''.join(pcmListPadded[:desired_samples])

    return padded_pcm

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM