我的目标是通过笔记本电脑麦克风录制我的声音并同时在python中添加效果。我需要的是类似于连接吉他或麦克风的音乐效果踏板,它会增加混响或回声或失真等。
我正在使用'pyaudio'和'wave'来录制和播放音频。使用'scikits.audiolab'将音频作为数组导入,并能够使用反转,剪辑,平铺等功能编辑此数组。音频数组的这种操作让我可以“添加”原始音频的效果。
我有一个问题,这不是一个真正的问题,它只是我想要的效果。假设我记录了“你好”这个词。我将记录功能设置为记录3秒钟。然后我拿这个音频阵列并将其平铺一次。现在,当我回来的时候,它会打两次问候,延迟效果。但是,两个hellos之间存在“空白空间”的时间间隔,这是因为音频在我完成打招呼后仍在录制。因此,当它重复时,单词之间的空白空间太大。我想消除这个空白空间,以便播放更快地打招呼你好。
我的老师建议穿线。他说我应该记录,同时抓住前500个样本,说出一个数字。他建议拍摄这500个样本并在录制时播放。我不太清楚如何实现这个。
我的问题是,如何同时录制,拍摄前500个样本,并创建一个新的数组,并将“效果”添加到原始录音中。
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("\nERROR.") # 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()
答案 0 :(得分:3)
首先,您提出的问题(能够在自动删除它们之间的安静空间时平铺音频样本)不是可以通过线程解决的问题。您需要分析录制的声音以确定存在或不存在静音的位置,或者只是允许用户指定录制何时结束。你可以用一个简单的循环完成后者:
在这个简单的例子中,使用线程没有任何好处。
建议的方法,记录并同时回放,似乎是解决另一个问题的方法,这个问题要复杂得多。在这种情况下,有两个主要困难:
答案 1 :(得分:0)
扩展卢克的回答:
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
在您的代码中,您承诺进行特定的录制时间。如果您编写了一个函数“isSilent
”,可以确定某个块是否是静默的,那么您的代码可能会更改为:
while len(frames) <= 0 or not isSilent(frames[-1]):
data = stream.read(CHUNK)
frames.append(data)
如果“isSilent
”难以编写,或者计算速度慢,则可以等待用户输入。 KeyboardInterrupt
是使用此方法的第一个黑客:
try:
while true:
data = stream.read(CHUNK)
frames.append(data)
except KeyboardInterrupt:
pass
这是一个黑客,而不是在生产中寻找用户输入的正确方法,但它会让你开始尝试这个。您将要查找或创建stopButtonHasBeenPressed
函数。
while not stopButtonHasBeenPressed():
data = stream.read(CHUNK)
frames.append(data)