无需预设时长,实现声音的持续播放与停止

霞舞
发布: 2025-08-21 19:18:01
原创
568人浏览过

无需预设时长,实现声音的持续播放与停止

本文旨在解决使用 PyAudio 库播放声音时,如何在不预先设定播放时长的情况下,实现声音的持续播放,并通过外部事件(例如按键释放)来停止声音。我们将分析问题代码,找出循环播放的错误原因,并提供修改方案,最终实现灵活的声音控制。

在使用 PyAudio 库进行音频编程时,一个常见的需求是在不预先确定播放时长的情况下,持续播放声音,并根据外部事件(例如,MIDI 控制器的按键释放)来停止播放。原始代码尝试通过一个 while 循环来实现这个功能,但存在一些逻辑上的问题,导致声音无法持续播放,或者无法正确停止。

分析与改进

原始代码的核心问题在于 while play == True 循环内部的逻辑。让我们再次审视一下:

while play == True:
    start_time = time.time()
    stream.write(vysledek)
    time.sleep(1)
    play = False

    stream.stop_stream()
play = True
登录后复制

这段代码的意图是循环播放声音数据 vysledek。然而,在每次循环迭代中,它会执行以下操作:

  1. 写入声音数据 stream.write(vysledek)。
  2. 暂停 1 秒 time.sleep(1)。
  3. 将 play 设置为 False,从而结束循环。
  4. 停止音频流 stream.stop_stream()。
  5. 在循环外部将 play = True,为下次MIDI触发做准备。

因此,循环只执行一次,导致声音只播放一秒钟。此外,stream.stop_stream() 被放置在循环内部,导致每次播放结束后立即停止音频流,这与持续播放的需求相悖。

解决方案

要实现持续播放,我们需要修改代码,移除不必要的 time.sleep(1) 和 play = False,并将 stream.stop_stream() 移到循环外部。更重要的是,我们需要根据MIDI消息来控制play变量,从而控制声音的播放和停止。

来画数字人直播
来画数字人直播

来画数字人自动化直播,无需请真人主播,即可实现24小时直播,无缝衔接各大直播平台。

来画数字人直播 0
查看详情 来画数字人直播

以下是修改后的代码示例:

import time
from rtmidi.midiutil import open_midiinput
import numpy as np
import pyaudio

p = pyaudio.PyAudio()
play = False  # 初始化为False,只有按下按键才播放

volume = 0.5
fs = 44100
fA = 440.0
fB = 493.88
fC = 523.25
fD = 587.33

frekvence = 440

frekvence_seznam = {
    (144, 32): fA,
    (144, 33): fB,
    (144, 34): fC,
    (144, 35): fD,
}

port = 0

midiin, port_name = open_midiinput(port)

stream = None # 初始化stream为None

try:
    while True:
        msg = midiin.get_message()

        if msg:
            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 * 1) * frekvence / fs # duration改为1,或者更小的值,减少计算量

                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)

                vysledek = volume * samples

                # 启动播放
                if not stream: # 如果stream未初始化,则初始化
                    stream = p.open(format=pyaudio.paFloat32,
                                    channels=1,
                                    rate=fs,
                                    output=True)
                play = True # 开始播放

            elif lepsi_klic == (128, 32) or lepsi_klic == (128, 33) or lepsi_klic == (128, 34) or lepsi_klic == (128, 35):  # 假设128代表按键释放
                print("停止播放")
                play = False  # 停止播放

            elif lepsi_klic == (144, 81):
                break # 退出主循环

        if play and stream: # 只有在play为True且stream已初始化时才播放
            stream.write(vysledek)

except KeyboardInterrupt:
    print("Interrupted by user")

finally:
    if stream:
        stream.stop_stream()
        stream.close()
    p.terminate()
    midiin.close_port()
    del midiin
登录后复制

修改说明:

  1. 初始化 play 为 False: 确保程序启动时声音不会自动播放。
  2. 移除 time.sleep(1) 和 play = False: 避免循环提前结束。
  3. 将 stream.stop_stream() 和 stream.close() 移到循环外部: 在程序退出前才关闭音频流。
  4. 根据 MIDI 消息控制 play 变量: 当检测到按键按下时,将 play 设置为 True,当检测到按键释放时,将 play 设置为 False。这里假设MIDI消息144代表按键按下,128代表按键释放,你需要根据你的MIDI设备实际情况进行调整。
  5. 在主循环中持续写入数据: 当 play 为 True 时,持续将声音数据写入音频流。
  6. duration改为1: 在生成声音数据时,duration改为1,或者更小的值,减少计算量,提高响应速度。
  7. 增加stream初始化判断: 在启动播放前,判断stream是否已经初始化,如果没有初始化,则初始化stream。
  8. 异常处理: 增加try...except...finally块,确保程序在异常情况下也能正确关闭音频流和MIDI端口。

注意事项

  • MIDI 消息: 确保你了解你的 MIDI 设备发送的按键按下和释放消息的格式。不同的设备可能使用不同的消息类型和值。
  • 性能: 持续写入音频数据可能会消耗大量的 CPU 资源。如果性能成为问题,可以考虑使用缓冲技术来减少写入频率。
  • 异常处理: 在实际应用中,应该添加更完善的错误处理机制,以应对各种可能出现的异常情况。

总结

通过修改循环逻辑,并根据 MIDI 消息动态控制播放状态,我们成功实现了在不预先设定播放时长的情况下,持续播放声音,并通过外部事件来停止播放的功能。这个方法可以应用于各种需要实时控制音频播放的场景,例如音乐游戏、交互式音频装置等。

以上就是无需预设时长,实现声音的持续播放与停止的详细内容,更多请关注php中文网其它相关文章!

相关标签:
最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
热门推荐
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号