我的目標是使用Python在計算機遊戲環境中播放符合以下要求的聲音。播放不同變異音調的聲音
取一些輸入WAV文件並隨機將音高變化爲原來的+/- 50%。改變採樣率似乎是用PyDub做這件事的一個簡單方法。
播放聲音。
能夠快速調用此功能,以便在實際播放中長時間和短時間的聲音重疊。
我花了24個工作小時尋找一種方法來滿足所有這些要求。我之前在Visual Basic中完成了這個工作,我很驚訝它在Python中的困難程度。
以下是我目前所知:
PyGame.Mixer可以玩重疊同時發出,但它必須在相同的採樣率播放所有。似乎沒有辦法改變音調。
PyDub可以通過更改採樣率來改變音高,但不能用重放聲音播放重疊聲音。而且,我必須將輸出聲音寫入文件,然後立即將其加載回去,這會讓人覺得很浪費。
WinSound可以播放PyDub的變化採樣率聲音,但不能與併發播放,甚至不能使用線程。
Playsound軟件包不適用於python 3.6。
如果我使用線程技術,PyAudio可以同時播放PyDub的變化採樣率聲音,但是,如果使用線程的時間不止兩次,並且會導致可怕的內存問題,並很快導致Python崩潰。
我的問題:我怎樣才能達到我的3個目標而不會造成問題?
這裏是最好的結果是我到目前爲止(這是PyAudio版本,這會導致如果測試超過一次以上的崩潰兩次):
from pydub import AudioSegment
from random import random, seed
from time import sleep
import os
import threading
import pyaudio
import wave
def PlayAsyncWithRandPitch(WavPath):
MyBaseFilename = os.path.basename(WavPath)
sound = AudioSegment.from_file(WavPath, format="wav")
seed()
octaves = ((random()-0.50))
print("random octave factor for this sound is: "+str(octaves))
print("current sound frame rate:"+str(sound.frame_rate))
new_sample_rate = int(sound.frame_rate * (2.0 ** octaves))
print("new sound frame rate:"+str(new_sample_rate))
newpitchsound = sound._spawn(sound.raw_data, overrides={'frame_rate': new_sample_rate})
MyTotalNewPath = os.getcwd()+"\\Soundfiles\\Temp\\Mod_"+MyBaseFilename
newpitchsound.export(MyTotalNewPath, format="wav")
SoundThread = threading.Thread(target=PAPlay, args=(MyTotalNewPath,))
SoundThread.start()
#=======================================================================================
#This function is just code for playing a sound in PyAudio
def PAPlay(filename):
CHUNK = 1024
wf = wave.open(filename, '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()
return
if __name__ == "__main__":
#Example sounds to test if more than one can play at once
PlayAsyncWithRandPitch(os.getcwd()+'\\Soundfiles\\RifleMiss.WAV')
sleep(0.2)
PlayAsyncWithRandPitch(os.getcwd()+'\\Soundfiles\\splash.wav')
sleep(0.2)
PlayAsyncWithRandPitch(os.getcwd()+'\\Soundfiles\\sparkhit1.WAV')
sleep(5.0)
預先感謝您對你的幫助!
將音頻剪輯預處理爲各種採樣率排列,以便在運行時直接渲染它們 –
我不知道該怎麼做。但謝謝你的回覆,我會考慮它:) – Zaorish9