2017-08-15 93 views
0

我想編寫一個非常基本的應用程序,將麥克風的音頻傳遞給揚聲器。在https://people.csail.mit.edu/hubert/pyaudio/中描述的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.基於事件

希望有人能照亮黑暗的地下室,我在現在的。

編輯:假設波形文件具有相同數量的通道和相同的速率,所以不需要轉換。

回答

0

把吞吐量()函數移動到線程後,它就像所期望的那樣工作。當我昨天嘗試這個時,我只是搞砸了線程啓動(在run()方法中代替init)。

所以這裏是完整的工作代碼。

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') 

後來我也將嘗試另一種方式colleauge今天建議,如果它確實表現得很好,我會把這裏作爲替代,太。使用線程方式很好,因爲我可以對流和wav文件使用不同的速率。

0

一位同事提供了下面的解決方案,這是一個非常原始的方法,但它的工作原理和理解這種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()