在Haskell中创建MIDI文件

Mar*_*ark 7 midi haskell

我想创建一个生成MIDI文件的简单程序.不,我不想使用Haskore,因为这个项目有点过分.我认为像这个库这样的东西就足够了.

我希望能做什么:

  • 创建新的MIDI文件;
  • 把一些事件写进去(我想及时控制速度,音高和位置);
  • 保存MIDI文件.

就这么简单,我敢打赌它并不难,但我找不到任何好的例子如何去做.

请提供一个基本示例或指出我在哪里可以找到有关在Haskell中创建MIDI文件的信息.

注意:我不是在问你关于好库的问题,我问你如何在Haskell中做到这一点(对于你认为在例子中使用的任何库而言).

Mar*_*ark 6

前言

好吧,我不确定这是一个好问题,但我不能再等了,所以这里是如何使用Haskell编写一些MIDI.我应该注意到这个主题几乎没有记录,除了一些看起来相当神秘的包描述.

适合我们需求的最简约包装是HCodecs,它似乎定期更新.我们对模块Codec.Midi感兴趣.

MIDI事件

在此库中,事件应表示为元组:

(time-offset, message)
Run Code Online (Sandbox Code Playgroud)

time-offset最后一个事件和新事件之间经过的时间点(参见下面如何设置每个节拍的刻度数).message必须是类型Message,可以在这里找到完整的构造函数列表.这些构造函数对应于所有基本的MIDI事件.

创建一个轨道

Track是一个事件列表.所以我们现在可以写一些非常简单的东西:

track0 = [(0,  NoteOn 0 60 80),
          (24, NoteOff 0 60 0),
          (0,  TrackEnd)]
Run Code Online (Sandbox Code Playgroud)

这是一个音符(60 =中间C),我们在这里使用了事件NoteOnNoteOff(它NoteOn0速度相同,因此在实践中人们倾向于仅使用它NoteOn).有关Google可以做什么的更多信息,请参阅Google格式的MIDI格式!

让我们创建一个包含E的轨道:

track1 = [(0,  NoteOn 0 64 80),
          (24, NoteOn 0 64 0),
          (0,  TrackEnd)]
Run Code Online (Sandbox Code Playgroud)

大!是时候将数据放入MIDI容器了.

一起来!

让我们创建表示整个MIDI文件的对象.我们将使用Midi数据类型的构造函数.

myMidi = Midi { fileType = MultiTrack, 
                timeDiv  = TicksPerBeat 24, 
                tracks   = [track0, track1] }
Run Code Online (Sandbox Code Playgroud)

而已!timeDiv定义轨道的量化,如果我们有24每个节拍的刻度,我们的音符将完全听到一个节拍(当然,你可以添加一些事件来设置速度和东西,试试吧!).

保存东西

要保存Midi我们应该使用exportFile(点击链接获取更多信息......好吧,开个玩笑甚至没有一行描述):

exportFile "my-midi.mid" myMidi
Run Code Online (Sandbox Code Playgroud)

完成.