首页 后端开发 Python教程 实时控制音频播放:基于PyAudio的无固定时长声音生成与停止

实时控制音频播放:基于PyAudio的无固定时长声音生成与停止

Aug 22, 2025 am 01:48 AM

实时控制音频播放:基于PyAudio的无固定时长声音生成与停止

本文旨在解决在使用PyAudio生成音频时,如何实现按下按钮开始播放声音,松开按钮立即停止播放的需求。通过修改原代码的循环结构,并移除不必要的延时和标志位重置,实现了音频的实时控制。同时,将停止音频流的操作移出循环,确保在需要停止时能够正确执行。

原始代码中存在一个问题,即在播放音频的while循环中,设置了time.sleep(1)和play = False,导致音频只播放一次就停止。为了实现按下按钮持续播放,松开按钮立即停止的效果,需要对循环结构进行调整,并确保在适当的时机停止音频流。

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

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

p = 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 float
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

try:
    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()

修改说明:

  1. 移除play标志位和time.sleep(1): 不再使用play标志位控制循环,直接在接收到MIDI消息时播放音频。移除了time.sleep(1),避免了不必要的延时。
  2. 将stream.stop_stream()移到按键抬起事件处理中: 当检测到MIDI按键抬起事件时(或者其他停止播放的条件),调用stream.stop_stream()停止音频流。
  3. 初始化stream: 在while循环之前初始化stream为None,并在需要播放音频时才创建音频流。并且在每次播放前检查stream是否已经被初始化或关闭,避免重复创建。
  4. 异常处理: 使用try...except...finally结构来确保程序在退出时正确关闭音频流和PyAudio。KeyboardInterrupt 用于捕获 Ctrl C 等中断信号,finally 块确保在任何情况下都能释放资源。
  5. 减小duration: 减小np.arange中的duration,避免卡顿。

注意事项:

  • 确保MIDI输入设备已正确连接并配置。
  • 根据实际需求调整volume、fs和frekvence_seznam等参数。
  • stream.close()和p.terminate()需要在程序结束时调用,以释放资源。建议将其放在finally块中。
  • 可以根据需要添加更复杂的控制逻辑,例如音量控制、音调调整等。

总结:

通过修改循环结构,并移除不必要的延时和标志位,可以实现基于PyAudio的实时音频播放控制。关键在于在适当的时机启动和停止音频流,并确保资源的正确释放。上述代码提供了一个基本的框架,可以根据实际需求进行扩展和定制。

以上是实时控制音频播放:基于PyAudio的无固定时长声音生成与停止的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

PHP教程
1585
276
python run shell命令示例 python run shell命令示例 Jul 26, 2025 am 07:50 AM

使用subprocess.run()可安全执行shell命令并捕获输出,推荐以列表传参避免注入风险;2.需要shell特性时可设shell=True,但需警惕命令注入;3.使用subprocess.Popen可实现实时输出处理;4.设置check=True可在命令失败时抛出异常;5.简单场景可直接链式调用获取输出;日常应优先使用subprocess.run(),避免使用os.system()或已弃用模块,以上方法覆盖了Python中执行shell命令的核心用法。

python seaborn关节图示例 python seaborn关节图示例 Jul 26, 2025 am 08:11 AM

使用Seaborn的jointplot可快速可视化两个变量间的关系及各自分布;2.基础散点图通过sns.jointplot(data=tips,x="total_bill",y="tip",kind="scatter")实现,中心为散点图,上下和右侧显示直方图;3.添加回归线和密度信息可用kind="reg",并结合marginal_kws设置边缘图样式;4.数据量大时推荐kind="hex",用

Python连接到SQL Server PYODBC示例 Python连接到SQL Server PYODBC示例 Jul 30, 2025 am 02:53 AM

安装pyodbc:使用pipinstallpyodbc命令安装库;2.连接SQLServer:通过pyodbc.connect()方法,使用包含DRIVER、SERVER、DATABASE、UID/PWD或Trusted_Connection的连接字符串,分别支持SQL身份验证或Windows身份验证;3.查看已安装驱动:运行pyodbc.drivers()并筛选含'SQLServer'的驱动名,确保使用如'ODBCDriver17forSQLServer'等正确驱动名称;4.连接字符串关键参数

python列表到字符串转换示例 python列表到字符串转换示例 Jul 26, 2025 am 08:00 AM

字符串列表可用join()方法合并,如''.join(words)得到"HelloworldfromPython";2.数字列表需先用map(str,numbers)或[str(x)forxinnumbers]转为字符串后才能join;3.任意类型列表可直接用str()转换为带括号和引号的字符串,适用于调试;4.自定义格式可用生成器表达式结合join()实现,如'|'.join(f"[{item}]"foriteminitems)输出"[a]|[

python httpx async客户端示例 python httpx async客户端示例 Jul 29, 2025 am 01:08 AM

使用httpx.AsyncClient可高效发起异步HTTP请求,1.基本GET请求通过asyncwith管理客户端并用awaitclient.get发起非阻塞请求;2.并发多个请求时结合asyncio.gather可显着提升性能,总耗时等于最慢请求;3.支持自定义headers、认证、base_url和超时设置;4.可发送POST请求并携带JSON数据;5.注意避免混用同步异步代码,代理支持需注意后端兼容性,适合用于爬虫或API聚合等场景。

优化用于内存操作的Python 优化用于内存操作的Python Jul 28, 2025 am 03:22 AM

pythoncanbeoptimizedFormized-formemory-boundoperationsbyreducingOverHeadThroughGenerator,有效dattratsures,andManagingObjectLifetimes.first,useGeneratorSInsteadoFlistSteadoflistSteadoFocessLargedAtasetSoneItematatime,desceedingingLoadeGingloadInterveringerverneDraineNterveingerverneDraineNterveInterveIntMory.second.second.second.second,Choos,Choos

SQLAlchemy 2.0 弃用警告及连接关闭问题解决指南 SQLAlchemy 2.0 弃用警告及连接关闭问题解决指南 Aug 05, 2025 pm 07:57 PM

本文旨在帮助 SQLAlchemy 初学者解决在使用 create_engine 时遇到的 "RemovedIn20Warning" 警告,以及随之而来的 "ResourceClosedError" 连接关闭错误。文章将详细解释该警告的原因,并提供消除警告以及修复连接问题的具体步骤和代码示例,确保你能够顺利地查询和操作数据库。

python shutil rmtree示例 python shutil rmtree示例 Aug 01, 2025 am 05:47 AM

shutil.rmtree()是Python中用于递归删除整个目录树的函数,能删除指定文件夹及其所有内容。1.基本用法:使用shutil.rmtree(path)删除目录,需处理FileNotFoundError、PermissionError等异常。2.实际应用:可一键清除包含子目录和文件的文件夹,如临时数据或缓存目录。3.注意事项:删除操作不可恢复;路径不存在时抛出FileNotFoundError;可能因权限或文件占用导致失败。4.可选参数:可通过ignore_errors=True忽略错

See all articles