5

我试图在 Python 中同时运行两种方法。其中一个播放声音,另一个录制声音。两种方法都可以正常工作,但我无法弄清楚如何在尝试多处理和线程的同时启动它们。而我现在几乎可以肯定它不能用线程来解决。

def listen_to_audio()

def play_audio()

有任何想法吗?(它们不必同时完成,但它们都应该在一秒钟内开始。)

那是代码,很抱歉没有在开头发布它:

import pyaudio
import wave
import sys
import time
from math import *
from getopt import *
import threading

def make_sin(f0=1000.,ampl=30000,rate=22050,length=5.):
  a = 2. * pi * f0/rate              
  n = int(rate * length)
  wav=''
  for i in range(0, n):
    f = int(ampl*sin(a*i))
    wav += chr(f & 0xFF) + chr((f & 0xFF00) >> 8)
  return wav



def play_audio(forHowLong):
    data = make_sin(f0=1000.,ampl=30000,rate=22050,length=5.)

    p = pyaudio.PyAudio() #sets up portaudio system
    stream = p.open(format=p.get_format_from_width(2),
                channels=1,
                rate=22050,
                output=True)

    start = time.time()
    while time.time() < start + forHowLong*0.5:    
            stream.write(data)

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


def listen_to_audio(forHowLong):
    CHUNK = 1024
    FORMAT = pyaudio.paInt16
    CHANNELS = 2
    RATE = 44100
    RECORD_SECONDS = forHowLong
    WAVE_OUTPUT_FILENAME = "output.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("* done 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()


def main():

#start play_audio and record_audio here at the same time



if __name__ == "__main__":
    main()
4

7 回答 7

4
import threading,time
def play1():
    while time.time() <= start_time:
        pass
    threading.Thread(target=listen_to_audio).start()
def play2():
    while time.time() <= start_time:
        pass
    threading.Thread(target=play_audio).start()
start_time=time.time()+20
threading.Thread(target=play1).start()
threading.Thread(target=play2).start()

这应该对你有用,它启动每个函数,并且在每个函数中它一直等到正确的时间:)

于 2012-11-16T18:38:46.990 回答
2

我会使用线程:

import threading

threads = []
threads.append(threading.Thread(target=listen_to_audio))
threads.append(threading.Thread(target=play_audio))

map(lambda x: x.start(), threads)

编辑:不确定 map 是否会绝对同时启动线程,但应该非常接近

于 2012-11-16T18:23:07.103 回答
2

你可以从:

import threading

threading.Thread(target=listen_to_audio).start()
threading.Thread(target=play_audio).start()
于 2012-11-16T18:24:03.770 回答
1

谢谢IT忍者,

您的代码完成了这项工作,但我不得不将其更改为:

def main():
start_time=time.time()+1
def play1():
    while time.time() < start_time:
        pass
    threading.Thread(target=listen_to_audio(5)).start()
def play2():
    while time.time() < start_time:
        pass
    threading.Thread(target=play_audio(5)).start()

threading.Thread(target=play1).start()
threading.Thread(target=play2).start()

现在它工作了:) 谢谢大家!

于 2012-11-16T21:48:49.303 回答
0

为什么要使用线程启动这两个功能?您可以简单地调用第一个函数并使用第一个函数中的线程启动第二个函数。

import threading


def play_audio():
    threading.Thread(target=listen_to_audio).start()
    #rest of code for play_audio

我认为这里的延迟会非常少。

于 2012-11-16T18:29:46.393 回答
0

事后很久,但是,

  1. 线程可能同时开始,但由于 Windows 的限制,播放/录制不会同时开始。实际上,幕后两者都有一个缓冲区,导致(未知或可控)延迟。

  2. 最好的方法是创建一个异步读/写流(一个同时进行读和写的流)。也就是说,使用回调函数创建一个流并定义 input=True 和 output=True (我在这里假设 pyaudio)。

我不确定 pyaudio 如何在幕后实现线程,尤其是在它阻塞音频的情况下,但另一个问题是 GIL(全局解释器锁)。我没有对事物的当前状态以及在不同 python 实现下的行为方式进行足够的研究,但是 IIRC 只有一个线程可以在给定时间运行 python 代码,所以 python 在大多数情况下对多线程不是很友好瞬间AFAIK

于 2013-12-24T05:46:27.313 回答
-1

我会创建一个def startBoth()来包装这两个函数,并根据需要同时导入 listen_to_audio 和 play_audio。一旦你开始startBoth(),它会调用这两个函数。

于 2012-11-16T18:20:49.043 回答