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

如何计算MIDI文件中每对音符的半音音程大小?

使用DryWetMIDI计算MIDI音符相邻音程(半音数)

核心思路

  • 读取MIDI文件,提取所有音符事件并按触发时间排序(MIDI文件的音符可能无序存储)
  • 遍历排序后的音符,通过前后音符的NoteNumber差值计算半音数(音程大小)

Unity实现代码

using UnityEngine;
using Melanchall.DryWetMidi.Core;
using Melanchall.DryWetMidi.Interaction;
using System.Collections.Generic;
using System.Linq;

public class MidiIntervalCalculator : MonoBehaviour
{
    public TextAsset midiFileAsset; // 在Inspector面板拖入MIDI文件(需设置为TextAsset类型)

    void Start()
    {
        if (midiFileAsset == null)
        {
            Debug.LogError("未指定MIDI文件,请拖入到Inspector");
            return;
        }

        // 读取MIDI文件流
        using (var midiFile = MidiFile.Read(midiFileAsset.bytes))
        {
            // 提取所有轨道的音符并按触发时间排序
            var sortedNotes = midiFile.GetNotes()
                                      .OrderBy(note => note.Time)
                                      .ToList();

            if (sortedNotes.Count < 2)
            {
                Debug.LogError("MIDI文件中音符数量不足,无法计算音程");
                return;
            }

            List<int> intervalList = new List<int>();
            Note prevNote = sortedNotes[0];

            // 遍历计算相邻音符的半音差
            for (int i = 1; i < sortedNotes.Count; i++)
            {
                Note currNote = sortedNotes[i];
                // 半音数 = 当前音符编号 - 前一个音符编号
                int interval = currNote.NoteNumber - prevNote.NoteNumber;
                // 若需取音程绝对值(忽略上下行),替换为 Mathf.Abs(interval)
                intervalList.Add(interval);
                prevNote = currNote;
            }

            // 输出结果(如C大调音阶会得到 2,2,1,2,2,2,1)
            Debug.Log("相邻音程半音列表:" + string.Join(", ", intervalList));
        }
    }
}

关键说明

  • GetNotes():DryWetMIDI的扩展方法,一次性提取MIDI所有轨道的音符事件
  • OrderBy(note => note.Time):必须排序,否则会出现跨时间的错误音程计算
  • NoteNumber:每个音符的半音编号属性(如C4对应60,D4对应62,差值2即为全音)
  • 关于CompareTo(Note):该方法用于比较音符的触发时间,而非音高,不能直接用来计算音程

注意事项

  • 若MIDI包含和弦(同时触发的多个音符),代码会按时间顺序依次计算所有音符的相邻差,如需仅计算旋律声部,需额外过滤特定轨道或筛选每个时间点的单音(如最高/最低音)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 01:37:31