如何解决使用NAudio从MIDI文件的一部分读取MIDI事件和消息
我是MIDI领域的新手,所以请不要对我残忍:) 我有一个Yamaha midi文件,其中包含一些部分,如Midi Header部分,CASM部分,OTS部分,MDB部分和MH部分。 我想对OTS科给予一些关注。 OTS部分包含ID = 4字节,Data Length = 4字节和Data。数据是一个midi文件结构块,但不包含注释,仅包含使用的通道之类的设置以及每个通道的设置,例如所用声音的MSB-LSB-PC,音量,和声等。 问题是如何检索使用的通道,如何检索使用的MSB-LSB-PC语音/鼓对? NAudio可以这样做吗?还是我必须使用其他Midi打包工具?
编辑:
OTS数据将至少包含一个OTS轨道。每个OTS轨道具有以下结构:
byte[0]->byte[3] = 'MTrk' (midi track header of SMF)
byte[4]->byte[7] = 256*256*256*byte[4] + 256*256*byte[5] + 256*byte[6] + byte[7] -> Data length on OTS Track.
byte[8]->byte[n] = SMF data of OTS Track.
因此,OTS数据将至少一次包含此结构。我将能够从每个OTS轨道读取信息,但是我不知道从那些OTS轨道数据SMF数据中获取那些MSB-LSB-PC信息的C#指令是什么。
解决方法
我建议您使用我的DryWetMIDI库。库文档上有一篇文章介绍了如何定义自定义块类并读取其数据:Custom chunks。
对于OTS块,从您提供的链接中可以看到,OTS块的数据实际上是没有标头块的MIDI文件。这样我们就可以将其内容读取为MIDI文件,并获取文件的曲目块。
让我们定义我们的块类:
public sealed class OtsChunk : MidiChunk
{
public const string Id = "OTSc";
public OtsChunk()
: base(Id)
{
}
public IEnumerable<TrackChunk> TrackChunks { get; private set; }
protected override void ReadContent(MidiReader reader,ReadingSettings settings,uint size)
{
var data = reader.ReadBytes((int)size);
using (var memoryStream = new MemoryStream(data))
{
var midiFile = MidiFile.Read(memoryStream,new ReadingSettings
{
NoHeaderChunkPolicy = NoHeaderChunkPolicy.Ignore
});
TrackChunks = midiFile.GetTrackChunks().ToArray();
}
}
public override MidiChunk Clone()
{
throw new NotImplementedException();
}
protected override uint GetContentSize(WritingSettings settings)
{
throw new NotImplementedException();
}
protected override void WriteContent(MidiWriter writer,WritingSettings settings)
{
throw new NotImplementedException();
}
}
由于您仅对阅读感兴趣,因此我们不会实现Clone
,GetContentSize
和WriteContent
。 (如果您希望能够手动创建此类块并将其写入MIDI文件,则也需要实现最后两种方法。)
现在我们可以读取Yamaha MIDI文件并获取OTS块:
var midiFile = MidiFile.Read("LionelRichie Hello_Amkey_TY.sty",new ReadingSettings
{
CustomChunkTypes = new ChunkTypesCollection
{
{ typeof(OtsChunk),OtsChunk.Id }
}
});
var otsChunk = midiFile.Chunks.OfType<OtsChunk>().FirstOrDefault();
然后,您可以从otsChunk.TrackChunks
的每个音轨块中获取常规的MIDI事件。例如,
var firstTrackChunkSysExEvents = otsChunk.TrackChunks.First().Events.OfType<NormalSysExEvent>();
var firstSysExEvent = firstTrackChunkSysExEvents.First();
var firstData = firstSysExEvent.Data;
firstData
将在OTS块的第一个磁道块中包含第一个sys ex事件的字节。请注意,数据将不包含前F0
个字节。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。