同时录制来自麦克风的音频并在 python 中播放效果 [英] Simultaneous record audio from mic and play it back with effect in python

查看:30
本文介绍了同时录制来自麦克风的音频并在 python 中播放效果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是通过笔记本电脑麦克风录制我的声音,同时在 python 中为其添加效果.我需要的是类似于音乐效果踏板,您可以在其中连接吉他或麦克风,并添加混响、回声或失真等.

My goal is to record my voice through the laptop mic and simultaneously adding an effect to it, in python. What I need is similar to a music effects pedal where you connect a guitar or mic and it adds reverb or echo or distortion, etc.

我正在使用pyaudio"和wave"来录制和播放音频.使用scikits.audiolab"将音频作为数组导入,并能够使用反转、剪辑、平铺等功能编辑此数组.音频数组的这种操作让我可以向原始音频添加"效果.

I am using 'pyaudio' and 'wave' to record and play back audio. Using 'scikits.audiolab' to import audio as a array and to be able to edit this array with with functions such as invert, clip, tile, etc. This manipulation of the audio array lets me "add" effects to the original audio.

我遇到了问题,这不是真正的问题,只是不是我想要的效果.假设我记录了你好"这个词.我的记录功能设置为记录 3 秒.然后我把这个音频数组平铺一次.现在,当我播放这个时,它会说两次你好,延迟效果.但是,两个你好之间有一个空白"的时间间隔,这是因为在我打完招呼后音频仍在录制.因此,当它重复时,单词之间的空格太多.我想消除这个空白空间,以便回放更快地打招呼.

I am having a problem, which isn't really a problem, it's just not the effect I want. Let's say I record the word "Hello". I have my record function set to record for 3 seconds. I then take this audio array and tile it once. Now, when I play this back, it will say hello twice, a delay effect. BUT, there is a time interval of 'empty space' between both hellos, which happens because the audio is still recording AFTER I finish saying hello. Therefore when it repeats, there's too much empty space between the words. I want to eliminate this empty space so that the playback says hello hello more quickly.

我的老师推荐线程.他说我应该记录,同时抓取前 500 个样本,说出一个数字.他建议在录音时采集这 500 个样本并回放它们.我不太确定如何实现这一点.

My teacher recommends threading. He says I should record, and simultaneously grab the first 500 samples, to say a number. He recommends to take these 500 samples and play them back while you record. I'm not quite sure how to implement this.

我的问题是,如何同时记录,取前 500 个样本,并创建一个新数组,并将效果"添加到原始记录中.

My question is, how to simultaneously record, take the first 500 samples, and create a new array with the "effect" added to the original recording.

import scikits.audiolab as audiolab
import pyaudio
import wave

def recordAudio():

    CHUNK = 1024
    FORMAT = pyaudio.paInt16
    CHANNELS = 1
    RATE = 44100
    RECORD_SECONDS = 3
    WAVE_OUTPUT_FILENAME = "audioOriginal.wav"

    p = pyaudio.PyAudio()

    stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)

    print("* recording:")

    frames = []

    for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
        data = stream.read(CHUNK)
        frames.append(data)

    print("* Finished recording.")

    stream.stop_stream()
    stream.close()
    p.terminate()

    wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(p.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(b''.join(frames))
    wf.close()

    # Duplicate audio and save as Actual
    frames, fs, encoder = audiolab.wavread('audioOriginal.wav')
    audiolab.wavwrite(frames,'audioActual.wav',fs)

def playAudio():

    import pyaudio
    import wave

    CHUNK = 1024

    wf = wave.open('audioActual.wav', 'rb')

    p = pyaudio.PyAudio()

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

    data = wf.readframes(CHUNK)

    while data != '':  
        stream.write(data)  
        data = wf.readframes(CHUNK)

    stream.stop_stream()
    stream.close()
    p.terminate()

def reverseAudio():

    frames, fs, encoder = audiolab.wavread('audioActual.wav')

    audiolab.wavwrite(frames[::-1],'audioActual.wav',44100)

def revert():
    frames, fs, encoder = audiolab.wavread('audioOriginal.wav')
    audiolab.wavwrite(frames,'audioActual.wav',fs)

def errorSelection():
    print("
ERROR.") # no option in menu
def showMenu():
    print("""
    1. Record audio
    2. Play audio
    3. Reverse audio
    4. Add delay
    5. Revert to original audio

    T to end program.
    """)

# Menu
def main():
    selecciones = {"1": recordAudio, "2": playAudio, "3": reverseAudio, "5": revert}
    while True:
        showMenu()
        seleccion = raw_input(u'What do you want to do? ')
        if "t" == seleccion:
            return
        elif "T" == seleccion:
            return
        toDo = selecciones.get(seleccion, errorSelection)
        toDo()

if __name__ == "__main__":
    main()

推荐答案

首先,您提出的问题(能够平铺音频样本,同时自动移除它们之间的安静空间)不是线程可以解决的问题.您需要分析录制的声音以确定哪里有或没有静音,或者只是让用户指定录制结束的时间.你可以用一个简单的循环来完成后者:

First, the problem you posed (being able to tile audio samples while automatically removing the quiet space between them) is not one that can be solved with threading. You need to analyze the recorded sound to determine where there is or is not silence, or simply allow the user to specify when recording should end. You can accomplish the latter with a simple loop:

  1. 打开音频硬件并开始录音.
  2. 创建一个空列表来存储音频块
  3. 请求一小块音频数据,附加到列表中
  4. 检查用户已请求结束录制.如果不是,则循环回到 3.
  5. 完成后,将块组合成一个数组以进行播放.

在这个简单的例子中,使用线程没有任何好处.

In this simple example, there is no benefit to using threading.

建议的方法是记录并同时播放,这似乎是解决另一个问题的方法,这个问题要复杂得多.在这种情况下,有两个主要困难:

The method suggested, to record and simultaneously play back, seems like a solution to a different problem, one that is much more complex. In this case, there are two major difficulties:

  1. 并非所有消费级声卡都能够同时录制和播放.寻找声称全双工"而不是半双工"的卡.
  2. 对着麦克风讲话并在短时间内听到自己的声音会极度分散注意力.为了使其正常工作,必须在不到大约 20 毫秒的时间内处理录制的音频并将其发送回声卡.在 44.1 kHz 时,这意味着您应该在每个循环周期读取少于 880 帧,如果处理跟不上,您将在输出中出现间隙.这是一个非常困难的问题,除非您有专门的软件来帮助.如果你真的想走这条路,你可以看看 Jack (http://jackaudio.org/),在大多数平台上提供低延迟音频访问,并有一个简单的 python 库(http://sourceforge.net/projects/py-jack/).线程可能对此类程序没有帮助.
  1. Not all consumer sound cards are capable of recording and playing simultaneously. Look for cards that claim "full duplex" instead of "half duplex".
  2. Speaking into a microphone and hearing yourself with a short delay is extremely distracting. To make this work properly, the recorded audio must be processed and sent back to the sound card in less than about 20 ms. At 44.1 kHz, this means you should be reading fewer than 880 frames per loop-cycle, and if the processing can't keep up, you will have gaps in the output. This is a surprisingly difficult problem unless you have specialized software to help. If you really want to go this way, you might look at Jack (http://jackaudio.org/), which provides low-latency audio access on most platforms and has an easy python library as well (http://sourceforge.net/projects/py-jack/). Threading will probably not be helpful in this type of program.

这篇关于同时录制来自麦克风的音频并在 python 中播放效果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆