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

求助:使用Drywetmidi调整MIDI播放时音符音高无效果

播放期间修改MIDI文件所有音符音高的解决方案

你用midiFile.ProcessNotes()修改的是磁盘或内存里的原始MIDI文件对象,但如果播放已经启动,播放引擎大概率已经把MIDI事件加载到缓冲区或者正在直接读取原始数据流,修改原对象根本同步不到正在运行的播放进程里,所以才没效果。

下面给你几种可行的解决办法:

方法1:用播放库的实时事件拦截(最推荐)

大部分MIDI播放库(比如你代码里用到的DryWetMIDI)都支持播放时拦截每个MIDI事件,实时修改音高后再发送到输出设备。示例代码:

using Melanchall.DryWetMidi.Multimedia;
using Melanchall.DryWetMidi.Core;

// 初始化播放设备,替换成你的设备名称
var outputDevice = OutputDevice.GetByName("你的MIDI输出设备");
var player = new MidiPlayer(outputDevice);

// 加载目标MIDI文件
var midiFile = MidiFile.Read("你的MIDI文件路径.mid");

// 注册播放时的事件处理逻辑
player.EventSent += (sender, e) =>
{
    // 处理NoteOn事件,修改音高(这里是降半音,注意限制在0-127范围内)
    if (e.Event is NoteOnEvent noteOn)
    {
        noteOn.NoteNumber = (SevenBitNumber)Math.Clamp(noteOn.NoteNumber - 1, 0, 127);
    }
    // 同步处理NoteOff事件,避免音符残留
    else if (e.Event is NoteOffEvent noteOff)
    {
        noteOff.NoteNumber = (SevenBitNumber)Math.Clamp(noteOff.NoteNumber - 1, 0, 127);
    }
};

// 启动播放
player.Play(midiFile);

方法2:暂停后修改文件再重新播放

如果你的播放库不支持实时拦截,可以先暂停播放,修改MIDI文件对象后重新启动播放:

// 按钮点击时的处理逻辑
if (player.IsPlaying)
{
    player.Stop();
    // 修改所有音符的音高,同时同步NoteOff事件
    midiFile.ProcessNotes(n => 
    {
        n.NoteNumber = (SevenBitNumber)Math.Clamp(n.NoteNumber - 1, 0, 127);
        foreach (var noteOff in n.NoteOffEvents)
        {
            noteOff.NoteNumber = n.NoteNumber;
        }
    });
    // 用修改后的文件重新播放
    player.Play(midiFile);
}

方法3:用MIDI弯音轮批量调整音高

还有一种更高效的方式:发送MIDI弯音轮消息,一次性调整所有正在播放的音符音高,不用逐个修改音符事件:

// 降半音:弯音轮默认范围是±2半音,0x4000是默认音高,0x3000对应降1半音
var pitchBendDown = new PitchBendEvent((ushort)0x3000);
outputDevice.SendEvent(pitchBendDown);

// 恢复原音高的话,发送0x4000的弯音值
var resetPitch = new PitchBendEvent(0x4000);
outputDevice.SendEvent(resetPitch);

注意:这种方法依赖你的MIDI合成器支持弯音轮功能,如果需要更大的弯音范围,还得先发送RPN消息调整弯音跨度。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 21:43:26