【发布时间】:2019-12-02 11:01:38
【问题描述】:
我根本没有线程方面的经验。
我想要做的就是播放声音,同时能够使用 GUI 更改音调(频率)。
此代码播放连续流,没有任何峰值或失真:
class Stream:
def __init__(self, sample_rate):
self.p = pyaudio.PyAudio()
self.sample_rate = sample_rate
# for paFloat32 sample values must be in range [-1.0, 1.0]
self.stream = self.p.open(format=pyaudio.paFloat32,
channels=1,
rate=sample_rate,
output=True)
self.samples = 0.
def create_sine_tone(self, frequency, duration):
# generate samples, note conversion to float32 array
self.samples = (np.sin(2 * np.pi * np.arange(self.sample_rate * duration) * frequency
/ self.sample_rate)).astype(np.float32)
def play_sine_tone(self, volume=1.):
"""
:param frequency:
:param duration:
:param volume:
:param sample_rate:
:return:
"""
# play. May repeat with different volume values (if done interactively)
while 1:
self.stream.write(volume * self.samples)
def terminate(self):
self.p.terminate()
def finish(self):
self.stream.stop_stream()
self.stream.close()
此代码创建 GUI。在left_click 和right_click 中,create_sine_tone() 创建一个新的频率波。但是,据我了解,它修改了threading 在play_sine_tone 中使用的内存,并且程序崩溃了。
def main():
window = Tk()
window.title("Piano reference")
window.geometry('350x200')
s = Stream(44100)
lbl = Label(window, text="A4")
lbl.grid(column=2, row=1)
def left_click(frequency):
s.create_sine_tone(frequency, 1.)
t = threading.Thread(target=s.play_sine_tone, args=(1,))
t.start()
lbl.configure(text=frequency)
def right_click(frequency):
s.create_sine_tone(frequency, 1.)
t = threading.Thread(target=s.play_sine_tone, args=(1,))
t.start()
lbl.configure(text=frequency)
btn1 = Button(window, text="<<", command=lambda: left_click(100))
btn2 = Button(window, text=">>", command=lambda: right_click(200))
btn1.grid(column=0, row=0)
btn2.grid(column=1, row=0)
window.mainloop()
如何修改 wave 以使程序不会崩溃?也许我可以在更改频率之前关闭线程?
【问题讨论】:
-
您在正确的轨道上,您可以在选择新频率后和播放新频率之前关闭现有线程播放声音。或者,根本不要使用线程并跟踪峰值,让现有频率在开始新频率之前完成其峰值。这样您就不会在频移时听到点击声。
标签: python audio python-multithreading pyaudio