[英]python threads for audio playing different sounds, do not seem to be locking correctly, and beginning of function returned to after thread calls
我正在研究基於鍵盤輸入從計算機播放聲音的代碼。 聲音存儲為wav文件並與PyAudio一起播放。 然而,為兩個連續的鍵盤敲擊播放的聲音之間的延遲太慢,所以我試圖添加線程以加快I / O時間。 但是,音頻現在變得沙啞,我不認為線程上的鎖是有效的。 這是相關代碼:
while threading.activeCount() < NUM_THREADS:
message, delta_time = midi_in.get_message()
if message:
if message[2] == 0:
continue
elif message and (str(message[1]) == "108" or str(message[1]) == "107"):
break
else:
t = threading.Thread(target=play, args=(message,))
lock = threading.Lock()
lock.acquire()
t.start()
lock.release()
def play(message):
WAVE_FILENAME = "final"+str(message[1]) + '.wav'
CHUNK = 1024
wf = wave.open(WAVE_FILENAME)
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()
非常感謝你的幫助!
我不認為線程上的鎖是有效的
原因是以下內容創建了一個新鎖:
lock = threading.Lock()
換句話說,您不是在循環的迭代中使用相同的鎖; 每次迭代都有自己的鎖。 結果,不發生同步。
我假設您必須將鎖傳遞給您的工作線程,如下所示:
def play(message, lock):
lock.acquire()
# do something with a restricted ressource
lock.release()
然后啟動一個線程並傳入鎖:
t = threading.Thread(target=play, args=(message, lock))
這里至少有兩個問題。
首先,正如NPE解釋的那樣,您正在為每個線程創建一個不同的鎖。 獲取鎖只會使您與獲取相同鎖的其他線程同步,而不是任何鎖。
其次,正如Theodros Zelleke所解釋的那樣,你實際上並沒有獲得工人線程中的鎖定; 你只是鎖定主線程,而它正在創建線程。 這沒有任何好處。
如果要確保一次只能運行一個線程,則需要執行以下操作:
lock = threading.Lock()
while threading.activeCount() < NUM_THREADS:
message, delta_time = midi_in.get_message()
if message:
if message[2] == 0:
continue
elif message and (str(message[1]) == "108" or str(message[1]) == "107"):
break
else:
t = threading.Thread(target=play, args=(message, lock))
t.start()
def play(message, lock):
WAVE_FILENAME = "final"+str(message[1]) + '.wav'
CHUNK = 1024
wf = wave.open(WAVE_FILENAME)
p = pyaudio.PyAudio()
with lock:
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()
請注意,我使用with lock:
而不是顯式lock.acquire()
和lock.release()
。 這不僅僅是方便 - 如果您在鎖定下執行任何操作都會拋出異常,則lock.release()
永遠不會被調用,除非您使用with
語句或try
。
如果你想阻止主線程,以及所有play
線程,你可以恢復你現有的鎖碼(或者更好,將它改為with lock:
塊),但要確保你把鎖定放在你實際的位置想要它。
同時:你意識到,如果你做對了,你將會實現一個無限積壓的單聲道合成器,所以直到之前的聲音全部完成才能播放聲音? 這是解決延遲問題的一種補充方法......
在我做的時候還有一些評論:
if message and …
if message:
? str(message[1]) == "108"
而不僅僅是message[1] == 108
?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.