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

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

本文旨在解决使用 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。然而,在每次循环迭代中,它会执行以下操作:

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

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

解决方案

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

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

import timefrom rtmidi.midiutil import open_midiinputimport numpy as npimport pyaudiop = pyaudio.PyAudio()play = False  # 初始化为False,只有按下按键才播放volume = 0.5fs = 44100fA = 440.0fB = 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 # 初始化stream为Nonetry:    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

修改说明:

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

注意事项

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

总结

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1368338.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月14日 08:41:46
下一篇 2025年12月14日 08:42:00

相关推荐

  • Pandas DataFrame排序与插入字符串行的专业教程

    本教程旨在解决在Pandas DataFrame中排序数值列,并在排序后的DataFrame顶部插入包含字符串的行的问题。我们将介绍如何创建一个包含混合数据类型的DataFrame,对其进行排序,然后插入包含字符串的新行,并提供完整的代码示例和详细的步骤说明,帮助读者掌握在Pandas中处理类似问题…

    好文分享 2025年12月14日
    000
  • 加速卷积函数:Numba 并行优化的实践指南

    本文旨在通过 Numba 库优化卷积函数的性能。通过将 Numpy 风格的代码替换为显式循环,并利用 Numba 的并行特性,可以显著提高计算速度。此外,还将讨论使用单精度浮点数和 GPU 加速的潜在方法,以进一步提升性能。 优化思路:显式循环与并行计算 使用 Numba 加速数值计算的关键在于避免…

    2025年12月14日
    000
  • Pandas DataFrame排序与插入字符串行:实用指南

    本文旨在解决在Pandas DataFrame中对数值列进行排序,并在排序后的DataFrame顶部插入包含字符串的行的问题。我们将介绍一种有效的方法,既能保证数值排序的正确性,又能灵活地在DataFrame中添加自定义的字符串信息行,最终生成符合需求的Excel文件。 Pandas DataFra…

    2025年12月14日
    000
  • 在 Pandas DataFrame 中对数值列进行排序并添加字符串行

    本文介绍了如何在 Pandas DataFrame 中对包含数值的列进行排序,并在排序后的 DataFrame 顶部添加包含字符串数据的新行。重点讲解了如何通过创建新的 DataFrame 并使用 pd.concat 函数将其与原始 DataFrame 连接,从而实现既能保留排序又能插入字符串行的需…

    2025年12月14日
    000
  • 求解Python中具有多个解的二元方程

    这段教程将指导你如何使用Python解决变量取值限定为0或1的二元方程组,这类问题在逻辑电路设计、密码学等领域有广泛应用。不同于传统的数值计算,这里的关键在于利用有限域上的线性代数方法,找到所有满足方程组的解。 理解问题 首先,我们需要明确问题的本质。给定一个二元方程组,其中每个变量只能取0或1。我…

    2025年12月14日
    000
  • 在 Pandas DataFrame 中排序并添加字符串行

    在 Pandas DataFrame 中,经常需要在排序后插入一行字符串作为标题或说明。直接将字符串添加到数值列会导致排序错误,因为列的数据类型会变成字符串。为了解决这个问题,我们可以先对 DataFrame 进行排序,然后创建一个新的 DataFrame 包含字符串行,最后将两个 DataFram…

    2025年12月14日
    000
  • 使用 PyAudio 播放声音并根据按键释放停止播放

    本文介绍如何使用 PyAudio 库生成和播放声音,并根据 MIDI 输入的按键释放事件停止声音的播放。我们将分析一个现有的代码示例,并提供修改建议,使其能够响应按键释放事件,实现更灵活的声音控制。### 理解问题原始代码存在的问题在于,它只能播放固定时长的声音,无法根据 MIDI 输入的按键释放事…

    2025年12月14日
    000
  • 使用Python解决具有多个解的二元方程

    本文旨在帮助读者理解并掌握使用Python解决具有多个解的二元方程的方法。文章将首先解释问题的数学背景,然后介绍两种不同的解决方案,分别使用itertools库和galois、sympy库。 问题描述 给定一组二元方程,其中变量只能取0或1的值,并且方程的结果始终为1。例如: X + Z = 1X …

    2025年12月14日
    000
  • 优雅地处理int函数包装的原始用户输入异常

    本文旨在讲解如何优雅地处理Python中int()函数包装的原始用户输入可能引发的异常。通过分析UnboundLocalError产生的原因,提供了一种在try块之前初始化变量的解决方案,确保即使在转换失败的情况下,程序也能正常运行,避免程序崩溃,提升用户体验。 在编写需要用户输入整数的Python…

    2025年12月14日
    000
  • 如何将 SHAP Summary Plot 保存为高质量图像文件

    本文详细介绍了如何将 SHAP (SHapley Additive exPlanations) 库生成的 summary_plot 可视化结果保存为图像文件。针对直接使用 plt.savefig() 可能导致空白图片的问题,教程强调了显式创建和引用 matplotlib 图形对象的重要性。通过初始化…

    2025年12月14日
    000
  • 解决 Python paramiko 依赖 bcrypt 轮子构建失败问题

    本文旨在解决在安装 Python paramiko 或 pysftp 库时,由于 bcrypt 模块的轮子(wheel)构建失败导致的错误。核心问题源于 bcrypt 4.0.0 版本的兼容性问题。通过将 bcrypt 降级到 3.2.2 版本,可以有效解决此编译错误,确保 paramiko 及相关…

    2025年12月14日
    000
  • 解决 Python paramiko 安装中 bcrypt 依赖构建失败问题

    本文旨在解决在安装 paramiko 或 pysftp 等Python库时,因其依赖项 bcrypt 版本问题导致的“Failed building wheel for bcrypt”错误。核心解决方案是针对 bcrypt 库的特定版本兼容性问题,通过将其降级到已知稳定且兼容的版本(例如 3.2.2…

    2025年12月14日
    000
  • 使用 Python 和 Boto3 在 AWS S3 中高效统计指定文件

    本教程详细介绍了如何使用 Python 和 Boto3 库高效地统计 AWS S3 存储桶中特定路径下符合命名模式的文件。文章重点阐述了 boto3.resource 相较于 boto3.client 在处理大量对象时的优势(例如自动分页),并提供了从 S3 URL 中提取桶名和前缀的方法。通过结合…

    2025年12月14日
    000
  • 如何使用 Python 和 Boto3 高效统计 AWS S3 特定文件

    本教程详细介绍了如何利用 Python 的 Boto3 库,高效地统计 AWS S3 存储桶中符合特定命名模式(例如 file_*.ts)的文件数量。文章将着重阐述 boto3.resource 的优势,包括其自动处理分页的能力,并提供清晰的代码示例,以实现对指定虚拟文件夹及其子文件夹内文件的精确计…

    2025年12月14日
    000
  • 加速卷积函数:使用 Numba 优化提升性能

    第一段引用上面的摘要:本文旨在指导如何使用 Numba 优化卷积函数的性能。通过避免在 Numba 代码中使用复杂的 NumPy 操作,并采用显式循环和并行化策略,可以将卷积函数的执行速度提升数倍。本文将提供优化后的代码示例,并讨论进一步提升性能的潜在方法,例如使用单精度浮点数和 GPU 加速。##…

    2025年12月14日
    000
  • 加速卷积函数的 Numba 优化实战教程

    本文旨在指导读者如何使用 Numba 优化卷积函数,通过避免创建临时数组、采用显式循环以及利用 Numba 的并行计算能力,显著提升代码执行效率。我们将对比原始 NumPy 实现和优化后的 Numba 实现,并深入探讨优化策略背后的原理,最终实现高达 5.74 倍的性能提升。 问题分析与优化思路 原…

    2025年12月14日
    000
  • Python asyncio应用中后台协程任务的正确运行姿势

    本文深入探讨了在Python asyncio和ASGI应用(如socketio)中,如何正确地在独立线程中运行异步协程任务,以避免RuntimeWarning: coroutine ‘…’ was never awaited错误,并确保主事件循环不被阻塞。通过结合…

    2025年12月14日
    000
  • 使用Python和Boto3高效统计AWS S3存储桶中特定文件数量

    本教程详细介绍了如何使用Python和Boto3库高效统计AWS S3存储桶中符合特定命名模式的文件数量。文章重点讲解了Boto3客户端与资源对象的选择、Prefix参数的正确使用、以及如何处理S3对象列表的自动分页,并提供了实用的代码示例,帮助用户精确筛选和统计S3文件。 理解S3对象列表与Bot…

    2025年12月14日
    000
  • 加速卷积函数的 Numba 优化实战

    本文旨在指导如何使用 Numba 优化卷积函数,通过将 NumPy 代码替换为显式循环,并利用 Numba 的并行化功能,显著提升代码执行效率。我们将深入探讨优化策略,并提供优化后的代码示例,最终实现比原始 NumPy 代码快数倍的加速效果。 优化思路:避免临时数组和利用显式循环 原始代码中使用了大…

    2025年12月14日
    000
  • 加速卷积函数的 Numba 优化实践

    本文将介绍如何使用 Numba 优化卷积函数,以实现显著的性能提升。原始的 NumPy 实现虽然简洁,但在大规模数据处理时效率较低。通过分析性能瓶颈,并结合 Numba 的特性,我们将提供一种基于纯循环和并行化的优化方案,该方案避免了 NumPy 高级特性在并行 Numba 代码中的潜在问题,并充分…

    2025年12月14日
    000

发表回复

登录后才能评论
关注微信