简体   繁体   English

如何使用pyaudio反转音频

[英]How to reverse audio with pyaudio

I've been tinkering around with pyaudio for a while now, trying to reverse a simple wave file with no success. 我已经纠结了pyaudio一段时间了,试图反转一个简单的wave文件没有成功。

In (my) theory I would only have to iterate from end to beginning through the file with every callback of pyaudio (1024 frames) fetch the audio data from the according index in the file, reverse the resulting string and play it. 用我的理论,我只需要从头到尾遍历整个文件,每次pyaudio回调(1024帧)都会从文件中的相应索引中获取音频数据,反转生成的字符串并进行播放。

Here is my code (only pyaudio callback and file handling, the rest is untouched from the example code): 这是我的代码(仅pyaudio回调和文件处理,其余未与示例代码保持一致):

import pyaudio
import wave
import time
import sys

if len(sys.argv) < 2:
    print("Plays a wave file.\n\nUsage: %s filename.wav" % sys.argv[0])
    sys.exit(-1)


index = 40*1024
wf = wave.open(sys.argv[1], 'rb')
wf.setpos(index)
p = pyaudio.PyAudio()


def callback(in_data, frame_count, time_info, status):
    global index
    data = wf.readframes(frame_count)
    data = data[::-1]
    index-=1024
    wf.setpos(index)

    return (data, pyaudio.paContinue)

stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
                channels=wf.getnchannels(),
                rate=wf.getframerate(),
                output=True,
                stream_callback=callback)


stream.start_stream()

while stream.is_active():
    time.sleep(0.1)

stream.stop_stream()
stream.close()
wf.close()

p.terminate()

I know this will crash when it reaches the file beginning, but it should play 40 × 1024 frames of reversed audio... 我知道这会在到达文件开头时崩溃,但是它应该播放40×1024帧反向音频...

If the file you want reversed is small enough to fit in memory, your best bet would be loading it entirely and reversing the data, then streaming it: 如果要反转的文件足够小以适合内存,最好的选择是将其完全加载并反转数据,然后流式传输:

import pyaudio
import wave

wavefile_name = 'wavefile.wav'
wf = wave.open(wavefile_name, 'rb')

p = pyaudio.PyAudio()
stream = p.open(format =
                p.get_format_from_width(wf.getsampwidth()),
                channels = wf.getnchannels(),
                rate = wf.getframerate(),
                output = True)

full_data = []
data = wf.readframes(1024)

while data:    
    full_data.append(data)
    data = wf.readframes(1024)

data = ''.join(full_data)[::-1]

for i in range(0, len(data), 1024):
    stream.write(data[i:i+1024])

However, if the file is too big to fit in memory, you'll need some way of reading the file backwards and feed into the sound system. 但是,如果文件太大而无法容纳在内存中,则需要某种方式向后读取文件并将其馈入声音系统。 That's an entirely different problem, because it involves some low level I/O programming to handle the backward reading. 这是一个完全不同的问题,因为它涉及一些底层I / O编程来处理向后读取。


Edit: after seeing your full code, I don't see any errors. 编辑:看到完整的代码后,我看不到任何错误。 The code runs properly in my computer, only to fail at the ending of the playback. 该代码可在我的计算机上正常运行,但仅在播放结束时失败。 However, you can do two things. 但是,您可以做两件事。 First, you can go to the end of the wavefile to play the entire sound backwards, using this: 首先,您可以使用以下命令转到wavefile的末尾以播放整个声音:

wf = wave.open(sys.argv[1], 'rb')
index = wf.getnframes() - 1024
wf.setpos(index)

Second, you have to modify the callback so it doesn't fail when the seek head goes beyond the beginning of the file: 其次,您必须修改回调,以便当查找头超出文件开头时它不会失败:

def callback(in_data, frame_count, time_info, status):
    global index
    data = wf.readframes(frame_count)
    data = data[::-1]
    index-=1024
    if index < 0:
        return (data, pyaudio.paAbort)
    else:
        wf.setpos(max(index,0))
        return (data, pyaudio.paContinue)

Other than that, it works pretty ok. 除此之外,它还可以。

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

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