
本文旨在解决在使用PyAudio生成音频时,如何实现按下按钮开始播放声音,松开按钮立即停止播放的需求。通过修改原代码的循环结构,并移除不必要的延时和标志位重置,实现了音频的实时控制。同时,将停止音频流的操作移出循环,确保在需要停止时能够正确执行。
原始代码中存在一个问题,即在播放音频的while循环中,设置了time.sleep(1)和play = False,导致音频只播放一次就停止。为了实现按下按钮持续播放,松开按钮立即停止的效果,需要对循环结构进行调整,并确保在适当的时机停止音频流。
以下是修改后的代码示例:
import timefrom rtmidi.midiutil import open_midiinputimport numpy as npimport pyaudiop = pyaudio.PyAudio()# play = True # 移除 play 标志位volume = 0.5 # range [0.0, 1.0]fs = 44100 # sampling rate, Hz, must be integer# duration = 5.0 # in seconds, may be float #Duration已经不需要了fA = 440.0 # sine frequency, Hz, may be floatfB = 493.88fC = 523.25fD = 587.33frekvence = 440frekvence_seznam = { (144, 32): fA, (144, 33): fB, (144, 34): fC, (144, 35): fD,}port = 0midiin, port_name = open_midiinput(port)stream = None #初始化streamtry: while True: msg = midiin.get_message() if msg: # klic = tuple(vstupni_list[:2]) message = msg klic = message[0] lepsi_klic = tuple(klic[:2]) print(message[0]) if lepsi_klic in frekvence_seznam: print("je to tam") frekvence = frekvence_seznam[lepsi_klic] period = 2 * np.pi x = period * np.arange(fs * 0.1) * frekvence / fs #减小duration,避免卡顿 sinus = np.sin(x) square = np.sign(sinus) triangle = 2/np.pi * np.arcsin(np.sin(x)) saw = abs((x % period) - 1) curvy_triangle = (abs((x % period) - 1)) ** 2 samples = (triangle).astype(np.float32) # for paFloat32 sample values must be in range [-1.0, 1.0] if stream is None or not stream.is_active(): #检查stream是否已经被初始化或关闭 stream = p.open(format=pyaudio.paFloat32, channels=1, rate=fs, output=True) vysledek = volume * samples # spusteni zvuku stream.write(vysledek) #移除while循环,持续播放 elif lepsi_klic == (144, 81): exit() else: #按键抬起时停止播放 if stream is not None and stream.is_active(): stream.stop_stream() # stream.close() # stream close放到循环外except KeyboardInterrupt: print("Exiting program")finally: if stream is not None and stream.is_active(): stream.stop_stream() if stream is not None: stream.close() p.terminate()
修改说明:
移除play标志位和time.sleep(1): 不再使用play标志位控制循环,直接在接收到MIDI消息时播放音频。移除了time.sleep(1),避免了不必要的延时。将stream.stop_stream()移到按键抬起事件处理中: 当检测到MIDI按键抬起事件时(或者其他停止播放的条件),调用stream.stop_stream()停止音频流。初始化stream: 在while循环之前初始化stream为None,并在需要播放音频时才创建音频流。并且在每次播放前检查stream是否已经被初始化或关闭,避免重复创建。异常处理: 使用try…except…finally结构来确保程序在退出时正确关闭音频流和PyAudio。KeyboardInterrupt 用于捕获 Ctrl+C 等中断信号,finally 块确保在任何情况下都能释放资源。减小duration: 减小np.arange中的duration,避免卡顿。
注意事项:
确保MIDI输入设备已正确连接并配置。根据实际需求调整volume、fs和frekvence_seznam等参数。stream.close()和p.terminate()需要在程序结束时调用,以释放资源。建议将其放在finally块中。可以根据需要添加更复杂的控制逻辑,例如音量控制、音调调整等。
总结:
通过修改循环结构,并移除不必要的延时和标志位,可以实现基于PyAudio的实时音频播放控制。关键在于在适当的时机启动和停止音频流,并确保资源的正确释放。上述代码提供了一个基本的框架,可以根据实际需求进行扩展和定制。
以上就是实时控制音频播放:基于PyAudio的无固定时长声音生成与停止的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1368296.html
微信扫一扫
支付宝扫一扫