You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MIDI控制器触发音频时非440Hz频率声音断续问题求助

问题分析与解决思路

你的代码里非440Hz频率声音断续,核心原因有两个:

1. 固定片段循环的相位断层

你在sound_play里预先生成1秒时长的波形样本,然后循环写入音频流。440Hz时,这段样本的结尾相位和开头几乎完全重合(计算出的结尾相位接近0),循环衔接无明显断层;但其他频率的样本首尾相位存在跳变,每次循环写入都会产生咔哒/断续感。

2. 多线程冲突风险

按下新MIDI按键时直接启动新线程,未停止之前可能还在运行的线程,多个线程同时向音频流写数据会导致声音混乱或断续。


具体修复步骤

步骤1:生成相位连续的循环波形

修改sound_play,生成整数个完整周期的波形样本,确保循环写入时首尾相位完全连续:

def sound_play(target_freq):
    # 计算单个周期的样本数,取最近整数
    cycle_samples = round(fs / target_freq)
    # 生成单个周期的三角波(原代码写了三角波逻辑但用了正弦,这里修正)
    t = np.linspace(0, 2*np.pi, cycle_samples, endpoint=False)
    triangle = 2/np.pi * np.arcsin(np.sin(t))
    # 转为带音量的float32格式样本
    samples = (volume * triangle).astype(np.float32)
    
    while not stop_event.is_set():
        stream.write(samples)

步骤2:确保单线程运行

处理MIDI按键按下事件时,先停止之前的线程再启动新线程,避免多线程冲突:

def play_sound(target_freq):
    global sound
    # 停止正在运行的旧线程
    if 'sound' in globals() and sound.is_alive():
        stop_event.set()
        sound.join()
        stop_event.clear()
    # 启动新线程并传入目标频率
    sound = threading.Thread(target=sound_play, args=(target_freq,))
    sound.start()

步骤3:修正MIDI消息处理逻辑

更新主循环,直接传递目标频率给play_sound,去掉依赖全局变量的逻辑:

while True:
    msg = midiin.get_message()
    if msg:
        message = msg[0]
        msg_type, note = message[0], message[1]
        print(message)
        
        if msg_type == 144:
            # 处理按键按下(Note On)
            if (msg_type, note) in frekvence_seznam:
                target_freq = frekvence_seznam[(msg_type, note)]
                play_sound(target_freq)
            elif note == 81:
                exit()
        elif msg_type == 128:
            # 处理按键松开(Note Off)
            if 'sound' in globals() and sound.is_alive():
                stop_event.set()
                sound.join()
                stop_event.clear()
                print("konec zvuku")

步骤4:移除冗余全局变量

删除原代码中的frekvence全局变量,改用参数传递目标频率,避免全局变量引发的线程同步问题。


额外优化建议

  • 改用PyAudio的回调模式替代线程循环写入,音频时序会更稳定,进一步降低断续风险。
  • 给MIDI消息处理加入防抖逻辑,避免误触发多次线程启停。

内容的提问来源于stack exchange,提问作者Mr.novak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 08:25:01