在python中同时播放多个声音

时间:2016-09-02 18:45:53

标签: python audio interactive

我一直在研究从样本列表中播放声音的方法,我找到了一些可以做到这一点的模块。

我使用 AudioLazy 模块使用以下脚本播放声音:

from audiolazy import AudioIO

sound = Somelist
with AudioIO(True) as player:
  player.play(sound, rate=44100)

此代码的问题在于它会停止整个应用程序,直到声音停止播放,我无法同时播放多个声音。

我的程序是交互式的,所以我想要的是能够同时播放多个声音,所以例如我可以运行这个播放5秒声音的脚本然后在第二个2我可以播放5秒再次响起。

我不希望整个节目停止播放声音。

3 个答案:

答案 0 :(得分:3)

这是使用pydub的更简单的解决方案。

使用overlay模块的AudioSegment功能,您可以非常轻松superimpose多个音频互相播放。

这是一个组合三个音频文件的工作代码。使用相同的概念,您可以将多个音频相互组合。

有关overlay函数here

的更多信息

pydub也支持多种音频格式。

from pydub import AudioSegment
from pydub.playback import play

audio1 = AudioSegment.from_file("chunk1.wav") #your first audio file
audio2 = AudioSegment.from_file("chunk2.wav") #your second audio file
audio3 = AudioSegment.from_file("chunk3.wav") #your third audio file

mixed = audio1.overlay(audio2)          #combine , superimpose audio files
mixed1  = mixed.overlay(audio3)          #Further combine , superimpose audio files
#If you need to save mixed file
mixed1.export("mixed.wav", format='wav') #export mixed  audio file
play(mixed1)                             #play mixed audio file

以下是根据我们的讨论进行的更新。
首先我们创建44KHz信号并保存到sound.wav
下一步读取波形文件并将信号保存到文本文件
然后创建三种输入信号变体来测试叠加 原始信号有dtype int16
然后我们创建三个音频片段 然后如上所述混合/叠加。 wav信号数据存储在test.txt

使用修改后的代码

import numpy as np
from scipy.io.wavfile import read
from pydub import AudioSegment
from pydub.playback import play
import wave, struct, math


#Create 44KHz signal and save to 'sound.wav'
sampleRate = 44100.0 # hertz
duration = 1.0       # seconds
frequency = 440.0    # hertz

wavef = wave.open('sound.wav','w')
wavef.setnchannels(1) # mono
wavef.setsampwidth(2) 
wavef.setframerate(sampleRate)

for i in range(int(duration * sampleRate)):
    value = int(32767.0*math.cos(frequency*math.pi*float(i)/float(sampleRate)))
    data = struct.pack('<h', value)
    wavef.writeframesraw( data )

wavef.writeframes('')
wavef.close()

#Read wave file and save signal to text file
rate, signal = read("sound.wav")

np.savetxt('test.txt', signal, delimiter=',')   # X is an array


#load wav data from text file
wavedata1 = np.loadtxt("test.txt", comments="#", delimiter=",", unpack=False, dtype=np.int16)

#Create variation of signal
wavedata2 = np.loadtxt("test.txt", comments="#", delimiter=",", unpack=False, dtype=np.int32)

#Create variation of signal
wavedata3 = np.loadtxt("test.txt", comments="#", delimiter=",", unpack=False, dtype=np.float16)

#create first audio segment
audio_segment1 = AudioSegment( 
    wavedata1.tobytes(), 
    frame_rate=rate,
    sample_width=2, 
    channels=1
)

#create second audio segment
audio_segment2 = AudioSegment( 
    wavedata2.tobytes(), 
    frame_rate=rate,
    sample_width=2, 
    channels=1
)

#create third audio segment
audio_segment3 = AudioSegment( 
    wavedata3.tobytes(), 
    frame_rate=rate,
    sample_width=2, 
    channels=1
)

# Play audio (requires ffplay, or pyaudio):
play(audio_segment1)
play(audio_segment2)
play(audio_segment3)

#Mix three audio segments
mixed1 = audio_segment1.overlay(audio_segment2)          #combine , superimpose audio files
mixed2  = mixed1.overlay(audio_segment3)          #Further combine , superimpose audio files
#If you need to save mixed file
mixed2.export("mixed.wav", format='wav') #export mixed  audio file
play(mixed2)                             #play mixed audio file

答案 1 :(得分:2)

我建议使用Pyaudio来执行此操作。

import pyaudio 
import wave
sound1 = wave.open("/path/to/sound1", 'rb')
sound2 = wave.open("/path/to/sound2", 'rb')

def callback(in_data, frame_count, time_info, status):
    data1 = sound1.readframes(frame_count)
    data2 = sound2.readframes(frame_count)
    decodeddata1 = numpy.fromstring(data1, numpy.int16)
    decodeddata2 = numpy.fromstring(data2, numpy.int16)
    newdata = (decodeddata1 * 0.5 + decodeddata2* 0.5).astype(numpy.int16)
    return (newdata.tostring(), pyaudio.paContinue)

答案 2 :(得分:1)

使用多个线程可以解决您的问题:

import threading
from audiolazy import AudioIO

sound = Somelist
with AudioIO(True) as player:
  t = threading.Thread(target=player.play, args=(sound,), kwargs={'rate':44100})
  t.start()