【问题标题】:PyAudio - How mix wave file into a continuous streamPyAudio - 如何将波形文件混合成连续流
【发布时间】:2018-01-23 20:29:15
【问题描述】:

我想编写一个非常基本的应用程序,将音频从麦克风传递到扬声器。如https://people.csail.mit.edu/hubert/pyaudio/ 所述,使用 pyaudio 非常简单。

def passthrough():
    WIDTH = 2
    CHANNELS = 1
    RATE = 44100

    p = pyaudio.PyAudio()

    def callback(in_data, frame_count, time_info, status):

        return (in_data, pyaudio.paContinue)

    stream = p.open(format=p.get_format_from_width(WIDTH),
                    channels=CHANNELS,
                    rate=RATE,
                    input=True,
                    output=True,
                    stream_callback=callback)

    stream.start_stream()

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

    stream.stop_stream()
    stream.close()

    p.terminate()

但现在我尝试在事件发生时将波形文件混合到此流中。这就是我现在卡住的地方。播放波形文件似乎也很容易。

def play_wave(wav_file):
    wf = wave.open(wav_file, 'rb')

    sample_width=wf.getsampwidth()
    channels=wf.getnchannels()
    rate=wf.getframerate()
    second=sample_width*channels*rate

    def callback(in_data, frame_count, time_info, status):
        data = wf.readframes(frame_count)
        return (data, pyaudio.paContinue)

    p = pyaudio.PyAudio()

    stream = p.open(format=p.get_format_from_width(sample_width),
                channels=channels,
                rate=int(rate),
                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()

这个时候,我有两个问题。

  1. 如何将波形输出混合到连续流中
  2. 如何触发 1. 基于事件

希望有人可以点亮我现在所在的黑暗地下室。

编辑:假设波形文件具有相同数量的通道和相同的速率,因此无需转换。

【问题讨论】:

    标签: python stream pyaudio


    【解决方案1】:

    将throughput() 函数移入线程后,它会按预期工作。当我昨天尝试这个时,我只是搞砸了线程启动(从 init 调用吞吐量,而不是在 run() 方法中)。

    这里是完整的工作代码。

    import pyaudio
    import wave
    import threading
    import time
    
    class AudioPass(threading.Thread):
        def __init__(self):
            threading.Thread.__init__(self)
        def run(self):
            self.passthrough()
        def passthrough(self):
            WIDTH = 2
            CHANNELS = 1
            RATE = 44100
    
            p = pyaudio.PyAudio()
    
            def callback(in_data, frame_count, time_info, status):
    
                return (in_data, pyaudio.paContinue)
    
            stream = p.open(format=p.get_format_from_width(WIDTH),
                            channels=CHANNELS,
                            rate=RATE,
                            input=True,
                            output=True,
                            stream_callback=callback)
    
            stream.start_stream()
    
            while stream.is_active():
                time.sleep(0.1)
    
            stream.stop_stream()
            stream.close()
    
            p.terminate()
    
    
    def play_wave(wav_file):
        wf = wave.open(wav_file, 'rb')
    
        sample_width=wf.getsampwidth()
        channels=wf.getnchannels()
        rate=wf.getframerate()
        second=sample_width*channels*rate
    
        def callback(in_data, frame_count, time_info, status):
            data = wf.readframes(frame_count)
            return (data, pyaudio.paContinue)
    
        p = pyaudio.PyAudio()
    
        stream = p.open(format=p.get_format_from_width(sample_width),
                    channels=channels,
                    rate=int(rate),
                    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()
    
    thread = AudioPass()
    thread.start()
    play_wave('C:/bell.wav')
    

    稍后我也会尝试今天一位同事建议的另一种方式,如果它也很好,我也会把它放在这里作为替代方案。使用线程方式很好,因为我可以对流和 wav 文件使用不同的速率。

    【讨论】:

      【解决方案2】:

      一位同事提供了以下解决方案,这是一种非常原始的方法,但它有效并且有助于理解这个 pyaudio 的工作原理。

      import time
      import pyaudio
      import numpy
      WIDTH = 2
      CHANNELS = 1
      RATE = 44100
      p = pyaudio.PyAudio()
      SINE_WAVE_FREQUENCY = 440.0 # In Hz
      SINE_WAVE_DURATION = 5.0 # In seconds
      SINE_WAVE_VOLUME = 0.5
      SINE_WAVE = (numpy.sin(2 * numpy.pi * numpy.arange(RATE * SINE_WAVE_DURATION) * SINE_WAVE_FREQUENCY / RATE)).astype(numpy.float32) * SINE_WAVE_VOLUME
      def loopback(in_data, frame_count, time_info, status):
              return (in_data, pyaudio.paContinue)
      stream = p.open(format=p.get_format_from_width(WIDTH), channels=CHANNELS, rate=RATE, input=True, output=True, stream_callback=loopback)
      stream.start_stream()
      def playsine():
              sinestream = p.open(format=pyaudio.paFloat32, channels=1, rate=RATE, output=True)
              sinestream.write(SINE_WAVE)
              sinestream.stop_stream()
              sinestream.close()
      while True:
              input("Press enter to play a sine wave")
              playsine()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多