解析 MIDI 文件以记录事件

Posted

技术标签:

【中文标题】解析 MIDI 文件以记录事件【英文标题】:Parsing MIDI file to note events 【发布时间】:2018-01-11 23:02:10 【问题描述】:

我目前正在尝试使用 NAudio MIDI 库解析 MIDI 文件以创建音符事件,该库可用于允许虚拟钢琴与 MIDI 轨道一起演奏。我有一个班级应该这样做,但是,有一个我无法弄清楚的错误。这是当前形式的类:

public MidiFile midi;

public float ticks;
public float offset;

// Use this for initialization
void Start () 
    //Loading midi file "mainSong.bytes" from resources folder
    //Its a midi file, extension has been changed to .bytes manually
    TextAsset asset = Resources.Load("mainSong") as TextAsset;
    Stream s = new MemoryStream(asset.bytes);
    //Read the file
    midi = new MidiFile(s, true);
    //Ticks needed for timing calculations
    ticks = midi.DeltaTicksPerQuarterNote;


public void StartPlayback()

    foreach (MidiEvent note in midi.Events)
    
        //If its the start of the note event
        if (note.CommandCode == MidiCommandCode.NoteOn)
        
            //Cast to note event and process it
            NoteOnEvent noe = (NoteOnEvent)note;
            NoteEvent(noe);
        
    


public void NoteEvent(NoteOnEvent noe)

    //The bpm(tempo) of the track
    float bpm = 150;

    //Time until the start of the note in seconds
    float time = (60 * noe.AbsoluteTime) / (bpm * ticks);

    int noteNumber = noe.NoteNumber;

    //Start coroutine for each note at the start of the playback
    StartCoroutine(CreateAction(time, noteNumber, noe.NoteLength));


IEnumerator CreateAction(float t, int noteNumber, float length)

    //Wait for the start of the note
    yield return new WaitForSeconds(t);
    //The note is about to play, do stuff here
    Debug.Log("Playing note: "+noteNumber);

目前,在尝试构建此代码时,该行的 Start 方法中存在错误 midi = new MidiFile(s, true); 错误是“无法从 system.io.stream 转换为字符串”

s 解析为字符串 midi = new MidiFile(s.ToString(), true); 允许构建代码,但是,在运行 Unity 项目时,同一行会出现此错误:“找不到文件”D:\ USER PROFILE\Documents\Unity Projects\New Unity Project\System.IO.MemoryStream"

有谁知道如何修复这些错误以允许此代码在 Unity 中运行?

【问题讨论】:

我想你可以做asset.text顺便说一句,如果你只是想要文本资产作为一个字符串 @mad.meesh:不,它需要一个文件名,而不是内容 @ThomasWeller 啊,好吧,我不知道这个库是什么,所以我只是笼统地说......因为他从 textassetstreamstring 【参考方案1】:

查看source code可以找到满足Stream, bool签名的构造函数:

/// <summary>
/// Opens a MIDI file stream for reading
/// </summary>
/// <param name="inputStream">The input stream containing a MIDI file</param>
/// <param name="strictChecking">If true will error on non-paired note events</param>
public MidiFile(Stream inputStream, bool strictChecking) :
    this(inputStream, strictChecking, false)


看来您使用的是旧版本的库。早在 2013 年,NAudio 就不支持从流中播放 MIDI。

查看历史,似乎在 2017-04-15 添加了 Stream 支持。

您应该尝试找到更新的版本,例如安装更新的 NuGet 包。


s.ToString()肯定帮不了你,因为:

它将Stream 对象转换为人类可读的格式。除了一些特殊的对象,它通常是类名。在您的情况下,类名是System.IO.MemoryStream(即s 的类型)。 然后它将在当前目录中查找一个名为System.IO.memoryStream 的文件。当前目录为D:\User\...\New Unity Project。 当然不会有文件,因为你有资源,而不是文件。

【讨论】:

以上是关于解析 MIDI 文件以记录事件的主要内容,如果未能解决你的问题,请参考以下文章

如何解析 Web MIDI API 输入消息 (onmidimesage)

MIDI 通道轨道相关

异步播放midi文件?

XG MIDI 文件格式

BLE MIDIMIDI 文件格式分析 ( MIDI 文件头解析 | MIDI 文件头标识 | MIDI 文件头长度 | MIDI 文件格式 | MIDI 轨道个数 | 基本时间 )

BLE MIDIMIDI 文件格式分析 ( MIDI 文件头解析 | MIDI 文件头标识 | MIDI 文件头长度 | MIDI 文件格式 | MIDI 轨道个数 | 基本时间 )(代码