精华内容
下载资源
问答
  • 如何制作midi文件
    2020-08-25 12:18:16

    c# midi播放器

    MIDI Slicer app

    介绍 (Introduction)

    Consider visiting my followup article here. It has improved code and a more thorough explanation of MIDI and the Midi library API.

    考虑在这里访问我的后续文章 它改进了代码,并对MIDI和Midi库API进行了更全面的说明。

    Quite some time ago, I wrote a VST and FL Studio plugin which used looped MIDI streams to play audio. I wrote it in C++, but I prototyped many of the MIDI operations in C# first. Later, I expanded this C# prototype code into a MIDI file editing library, which I've provided here, along with an example utility that allows for simple editing of a MIDI file.

    相当一段时间以前,我编写了一个VST和FL Studio插件,该插件使用循环的MIDI流播放音频。 我用C ++编写,但是我首先用C#制作了许多MIDI操作的原型。 后来,我将此C#原型代码扩展到了我在此处提供的MIDI文件编辑库中,并提供了一个示例实用程序,该实用程序允许简单地编辑MIDI文件。

    Update: Added time signature support. Small bugfix in playback.

    更新:添加了时间签名支持。 播放中的小错误修正。

    Update 2: Added MIDI message classes for each type of MIDI operation, and several features to the MidiSlicer app

    更新2:为每种MIDI操作类型添加了MIDI消息类,并为MidiSlicer应用添加了一些功能

    Update 3: Added Normalize and Level scaling. Made the Offset and Length floating point

    更新3:添加了标准化和级别缩放。 制作偏移和长度浮点

    Update 4: Improvements to correctness of API created MIDI sequences and files, better preview and save.

    更新4:改进API创建的MIDI序列和文件的正确性,更好地预览和保存。

    Update 5: Added Transpose() option to API and to GUI

    更新5:向API和GUI添加了Transpose()选项

    Update 6: API enhancements and improvement to overall GUI behavior

    更新6: API增强和整体GUI行为的改进

    概念化这个混乱 (Conceptualizing this Mess)

    MIDI stands for Musical Instrument Digital Interface. What it does is allow you to automate digital instruments similar to how one of those old player pianos work. MIDI contains all the note information - basically the "sheet music" for a song which it can then broadcast to up to 16 different digital audio devices like drum machines and synthesizers, or MIDI capable pianos and the like. Your Windows machine contains a default device that can play numerous synthesized sounds emulating various instruments like pianos and guitars. Your phone does too. Your systems can use this to play MIDI files out of your default audio device - usually your primary sound card or audio hardware. MIDI is often used by phones to store ring tones. That having been said, MIDI was originally designed for musicians, and its primary purpose is to allow musicians to record or "sequence" their performance and save it to a file for replay or editing.

    MIDI代表乐器数字接口。 它的作用是让您自动化数字乐器,就像那些老式钢琴之一的工作方式一样。 MIDI包含所有音符信息-基本上是歌曲的“乐谱”,然后可以将其广播到多达16种不同的数字音频设备,例如鼓机和合成器,或具有MIDI功能的钢琴等。 您的Windows计算机包含一个默认设备,该设备可以播放模拟钢琴和吉他等各种乐器的大量合成声音。 您的手机也可以。 您的系统可以使用它来播放默认音频设备(通常是主声卡或音频硬件)中的MIDI文件。 手机通常使用MIDI来存储铃声。 话虽如此,MIDI最初是为音乐家而设计的,其主要目的是允许音乐家录制或“排序”他们的演奏并将其保存到文件中以进行重放或编辑。

    MIDI协议 (The MIDI Protocol)

    MIDI is first and foremost a wire protocol, and secondly a file format. The protocol consists of realtime MIDI "messages". All a MIDI file is in its essence is the protocol stream stored as a file along with a delta time for each "message" - the time in the song the "message" should be played. A delta time plus a message is called a MIDI event. MIDI events are stored as a stream in the file for replay later. Therefore, understanding the protocol is fundamental to understanding the file format.

    MIDI首先是有线协议,其次是文件格式。 该协议包括实时MIDI“消息”。 实质上,所有MIDI文件都是作为文件存储的协议流以及每个“消息”的增量时间-“消息”中歌曲应播放的时间。 增量时间加上一条消息称为MIDI事件。 MIDI事件作为流存储在文件中,以供稍后重播。 因此,了解协议是了解文件格式的基础。

    Having been designed in the 1980s, MIDI defines an 8 bit wire protocol. Any strings are ASCII, and most values are 0-127 (7 bits plus a leading 0 bit) with some values being 0-255 (8 bit). There are occasionally multibyte values (larger than 8 bits) in the stream. These are always big-endian, so on Intel platforms you'll have to swap the byte order.

    MIDI是1980年代设计的,它定义了8位线协议。 任何字符串都是ASCII,大多数值为0-127(7位加上前导0位),有些值为0-255(8位)。 流中偶尔会有多字节值(大于8位)。 这些始终是big-endian,因此在Intel平台上,您必须交换字节顺序。

    A MIDI message at the very least contains an 8 bit "status byte." However, a message may contain additional fields/payload depending on the value of the status byte. The status byte tells us both the "type" of message (in the first 4 bits), plus the "channel" (midi "device") the message is intended for in the final 4 bits - remember the MIDI protocol allows control of up to 16 devices - from here on referred to as channels. Most MIDI messages have additional fields. For example, a "note on" message contains the note number, and the velocity of the note to be played. The following MIDI message is composed of 3 bytes. In the first byte, the 9 half is the code for note on, and 0 half is the code for channel 0. Next the node number for note C, octave 5 (48 hex below) is to be played at maximum velocity (127/7F) as indicated by the final byte, which must have the high bit set to zero, leaving you with a numeric range of 0-127:

    MIDI消息至少包含一个8位的“状态字节”。 但是,一条消息可能包含其他字段/有效负载,具体取决于状态字节的值。 状态字节告诉我们消息的“类型”(在前4位中)以及消息在最后4位中用于“通道”(中部“设备”)-记住MIDI协议允许控制向上到16个设备-从此处称为通道。 大多数MIDI消息都有其他字段。 例如,“ note on”消息中包含音符编号和要播放的音符的速度。 以下MIDI信息由3个字节组成。 在第一个字节中,9的一半是音符打开的代码,0的一半是通道0的代码。接下来,音符C的节点号八度5(下面的48十六进制)将以最大速度(127 / 7F),如最后一个字节所示,该字节必须将高位设置为零,从而使您的数字范围为0-127:

    90 48 7F
    
    

    This will cause the device to strike the note and hold it until a note off message is found for that same note:

    这将导致设备敲击该音符并按住它,直到找到该音符的音符关闭消息为止:

    80 48 7F
    
    

    The only difference between a note off and a note on is the first nibble is 8 hex instead of 9 hex. Most devices won't use the velocity byte for a note off message but send it anyway. I typically will use the same value I specified in note on, or zero in cases where I don't know the corresponding note on velocity. Either way should work with MIDI devices out there, but it's always possible that a device is weird. The thing about this protocol is you have to be kind of forgiving of dodgy devices, and that requires good, old fashioned testing.

    音符关闭和音符打开之间的唯一区别是第一个半字节是8进制而不是9十六进制。 大多数设备不会将速度字节用于音符关闭消息,但无论如何都要发送。 通常,我将使用在音符上指定的相同值,或者在我不知道速度的相应音符的情况下使用零。 两种方法可以与MIDI设备一起使用,但是设备总是很奇怪。 关于该协议的问题是,您必须宽容狡猾的设备,这需要良好的老式测试。

    Again, different messages are different lengths. The patch/program change message indicates which "sound" a channel will use. Often MIDI devices such as synthesizers can produce many different kinds of sounds. This message allows you to send a 7-bit (0-127/7F) code (encoded as a full byte with the high bit 0) that indicates the patch to use. Selecting patch 2 gives us:

    同样,不同的消息具有不同的长度。 补丁/程序更改消息指示通道将使用哪个“声音”。 诸如合成器之类的MIDI设备通常可以产生多种不同的声音。 此消息使您可以发送7位(0-127 / 7F)代码(编码为全字节,高位为0),指示要使用的补丁。 选择补丁2将为我们提供:

    C0 02
    
    

    You may have noticed that aside from the status byte, all of our values are 7-bit encoded as 8-bit with the high bit of zero leaving us with an effective range of values from 0-127/7F. This is important because of an optimization called a running status byte which I'll cover briefly, and is covered as well at the links in the Further Reading section.

    您可能已经注意到,除了状态字节以外,我们所有的值都被7位编码为8位,高位为零,从而使我们的有效值范围为0-127 / 7F。 这一点很重要,因为有一个称为运行状态字节的优化,我将简要介绍它,在“ 进一步阅读”部分的链接中也将进行介绍。

    A MIDI message may be a complete message with a status byte, or the status byte may be omitted in which case the previous status will be used. This allows for "runs" of multiple messages of the same type and sent to the same channel but with different parameters. Most of the time, this just causes extra complication for an optimization that often doesn't matter, so you don't really have to emit it but you have to be able to read it. That being said, MIDI is technically bandwidth limited so if you have a lot of events it might make sense to emit it as well.

    MIDI消息可以是带有状态字节的完整消息,或者可以省略状态字节,在这种情况下,将使用先前的状态。 这允许“运行”相同类型的多个消息,并发送到相同通道但参数不同。 在大多数情况下,这只会给优化带来额外的复杂性,而这种优化通常并不重要,因此您实际上不必发出它,但必须能够阅读它。 话虽这么说,MIDI在技术上受带宽限制,所以如果您有很多事件,那么发出它也是很有意义的。

    Occasionally in MIDI messages, such as a the pitch bend (status nibble E), you'll find 14-bit values are used in messages. These are encoded by the least significant 7-bits (in an 8-bit field with high bit 0) followed by the most significant 7-bits (in an 8-bit field with high bit 0)

    有时在MIDI消息中,例如弯音(状态半字节E),您会发现消息中使用了14位值。 它们由最低有效7位(在高位0的8位字段中)编码,然后由最高有效7位(在高位0的8位字段中)编码

    You can find a complete list of MIDI messages at the links in the Further Reading section.

    您可以在“ 进一步阅读”部分的链接中找到MIDI消息的完整列表。

    MIDI文件格式 (The MIDI File Format)

    A MIDI file is laid out in "chunks." Each chunk is a fourCC ASCII value that indicates the "type" of the chunk. This is followed by a big-endian 4-byte integer that indicates the length of the data that follows, which is the actual data for the chunk. The first chunk type must be "MThd" and the only other common chunk type is "MTrk" Any chunk types not understood should be skipped.

    MIDI文件以“块”布局。 每个块都是一个fourCC CC ASCII值,指示该块的“类型”。 这之后是一个大字节序的4字节整数,该整数指示后面的数据的长度,该数据是块的实际数据。 第一个块类型必须为“ MThd”,唯一的其他公共块类型为“ MTrk”。任何不了解的块类型都应跳过。

    The "MThd" chunk contains the MIDI file type (usually 1), the track count, and the timebase (commonly 480), each encoded as big-endian 16-bit words.

    “ MThd”块包含MIDI文件类型(通常为1),音轨计数和时基(通常为480),每个均编码为大端16位字。

    The "MTrk" chunk contains a track which is a sequence of note on/off message events and other MIDI events. Each event is a delta time followed by a partial or complete MIDI message. The first MIDI track in a MIDI file is usually "special" in that it contains meta information about the MIDI file, including critical data like the tempo information, but also things like lyrics.

    “ MTrk”块包含一个轨道,该轨道是音符开/关消息事件和其他MIDI事件的序列。 每个事件都是一个增量时间,然后是部分或完整的MIDI消息。 MIDI文件中的第一个MIDI轨道通常是“特殊”的,因为它包含有关MIDI文件的元信息,包括诸如节奏信息之类的关键数据,还包括歌词之类的东西。

    The delta time is encoded as a "variable length integer" which I won't cover here, but is covered at the Standard MIDI File Format link in the Further Reading section. It indicates the number of MIDI "ticks" since the last event (hence delta.) I'll get into timing below.

    增量时间被编码为“可变长度整数”,在此不做介绍,但在“进一步阅读”部分的“标准MIDI文件格式”链接中进行了介绍。 它指示自上次事件以来的MIDI“滴答声”的数量(因此发生变化)。

    The message that follows can be a full MIDI message, or partial MIDI message with the status byte omitted as described previously.

    后面的消息可以是完整的MIDI消息,也可以是部分MIDI消息,如前所述,其状态字节被省略了。

    MIDI文件中的定时 (Timing in MIDI Files)

    MIDI timing is measured in ticks. The timing of a tick varies depending on the timebase of the MIDI file, which is measured in ticks-per-quarter-note. This is also known as pulses-per-quarter-note or PPQ. That gives you the length of one beat, at the default 4/4 time. The default tempo is 120 beats per minute. The tempo and time signature are set using MIDI events with special MIDI "meta" messages (status byte of FF) and can be set throughout the playback. These are typically in the first track, and are global to all tracks.

    MIDI音调以滴答度数为单位。 滴答声的时序因MIDI文件的时基而异,该时基以每四分音符滴答声为单位。 这也称为每四分之一脉冲数或PPQ。 这样一来,您的拍子长度将达到默认的4/4时间。 默认速度为每分钟120次。 使用带有特殊MIDI“元”消息(FF的状态字节)的MIDI事件设置速度和拍号,并可在整个播放过程中进行设置。 这些通常位于第一轨道,并且对所有轨道都是全局的。

    I've included a couple of MIDI files I downloaded in the project directory for testing. Any copyright information is available in the MIDI file itself. A-Warm-Place.mid uses features not fully supported by this library but it "mostly" plays. The reason I've included it is it's a useful test for extending the library in the future to support SMPTE timing and proper sysex transmission.

    我包含了一些我下载到项目目录中的MIDI文件以进行测试。 MIDI文件本身中提供了所有版权信息。 A-Warm-Place.mid使用的功能未得到该库的完全支持,但“大多数”可以播放。 我包含它的原因是,这是将来扩展库以支持SMPTE计时和正确sysex传输的有用测试。

    编码此混乱 (Coding this Mess)

    The main class is MidiFile, suitably named because this class represents MIDI data in the MIDI file format. It's not necessarily backed by a physical file. It can be created and operated on entirely in memory. It provides access to common features that apply to all tracks, plus timing information, and access to the meta information in track 0. Read a MIDI file using MidiFile.ReadFrom() and write a MIDI file using WriteTo().

    主类是MidiFile ,因此可以适当命名,因为此类表示MIDI文件格式的MIDI数据。 它不一定由物理文件支持。 它可以完全在内存中创建和操作。 它提供对适用于所有轨道的通用功能的访问,以及定时信息,以及对轨道0中的元信息的访问。使用MidiFile.ReadFrom()读取MIDI文件,并使用WriteTo()写入MIDI文件。

    The other really important class here is MidiSequence which represents a single sequence or track in a MidiFile. This class allows you to access all of its MidiEvents either as relative delta based or absolute time, and provides access to any meta information stored in the sequence. Sequences can be merged with Merge() or concatenated with Concat(). They can be stretched or compressed with Stretch(). You can retrieve a range of events using GetRange(). Note that some of these operations appear on MidiFile as well and those will operate on each track/sequence in the file.

    另一个真正重要的类是MidiSequence ,它表示MidiFile的单个序列或音轨。 此类允许您基于相对增量或绝对时间访问其所有MidiEvent ,并提供对序列中存储的任何元信息的访问。 序列可以与Merge()或与Concat()串联。 可以使用Stretch()拉伸或压缩它们。 您可以使用GetRange()检索一系列事件。 请注意,其中一些操作也会出现在MidiFile ,而这些操作将在文件中的每个音轨/序列上进行。

    In the demo code, we process each track depending on the settings in the UI:

    在演示代码中,我们根据UI中的设置处理每个轨道:

    if (NormalizeCheckBox.Checked)
        trk.NormalizeVelocities();
    if (1m != LevelsUpDown.Value)
        trk.ScaleVelocities((double)LevelsUpDown.Value);
    var ofs = OffsetUpDown.Value;
    var len = LengthUpDown.Value;
    if (0 == UnitsCombo.SelectedIndex) // beats
    {
        len = Math.Min(len * _file.TimeBase, _file.Length);
        ofs = Math.Min(ofs * _file.TimeBase, _file.Length);
    }
    ...
    if (1m != StretchUpDown.Value)
        trk = trk.Stretch((double)StretchUpDown.Value, AdjustTempoCheckBox.Checked);
    
    

    First we handle velocity normalization and scaling. Next, we grab the offset and length of the selection. Then if it's specified in beats, we use the TimeBase to compute the beats. The rest of the Math calls just clamp the values to the maximum allowable length.

    首先,我们处理速度归一化和缩放。 接下来,我们获取选择的偏移量和长度。 然后,如果以拍子指定,则使用TimeBase来计算拍子。 其余的Math调用仅将值限制为最大允许长度。

    Next, if our length and offsets are different than 0 and the length of the sequence we get the range of events within that time.

    接下来,如果我们的长度和偏移量不同于0,并且序列的长度不同,那么我们将获得该时间范围内的事件范围。

    I've ommitted a bunch of code in the middle from the listing above, but it handles the rest of the features in the UI by calling the appropriate MidiSequence API methods.

    我在上面的清单中省略了很多代码,但是它通过调用适当的MidiSequence API方法来处理UI中的其余功能。

    Finally, if we've specified a stretch value other than 1, we call Stretch() to stretch the track.

    最后,如果我们指定的拉伸值不是1,则调用Stretch()拉伸轨道。

    MidiEvent simply contains a Position in ticks, and a MidiMessage. Depending on whether this event was retrieved through Events or AbsoluteEvents, the Position will be a delta time or an absolute time, respectively.

    MidiEvent只是包含一个以刻度为单位的Position和一个MidiMessage 。 根据该事件是通过Events还是AbsoluteEvents检索的, Position将分别为增量时间或绝对时间。

    MidiMessage and its derivatives represent MIDI messages of various lengths such as MidiMessageByte and MidiMessageWord. There are also the special MidiMessageMeta and MidiMessageSysex classes which represent a MIDI meta message and a MIDI system exclusive message respectively. See the Standard MIDI File Format link in the Further Reading section for more about these messages. In addition, there are MIDI messages for each type of MIDI operation, such as MidiMessageNoteOn, MidiMessageCC, and MidiMessageChannelPitch.

    MidiMessage及其派生词表示各种长度的MIDI消息,例如MidiMessageByteMidiMessageWord 。 还有特殊的MidiMessageMetaMidiMessageSysex类,分别表示MIDI元消息和MIDI系统专有消息。 有关这些消息的更多信息,请参见“进一步阅读”部分的“标准MIDI文件格式”链接。 此外,每种MIDI操作类型都有MIDI消息,例如MidiMessageNoteOnMidiMessageCCMidiMessageChannelPitch

    MidiContext is a class that represents the current "state" of a MIDI sequence. When using GetContext(), one of these instances will be returned from the function and it will give you all of the current note velocities, control positions, pitch wheel position, aftertouch information and the rest. This allows you to know what is playing and how at any given moment within the sequence.

    MidiContext是一个类,代表MIDI序列的当前“状态”。 使用GetContext() ,将从函数中返回这些实例之一,它将为您提供所有当前音符速度,控制位置,音高轮位置,触后信息以及其他信息。 这样一来,您就可以知道正在播放什么以及在序列中的任何给定时刻如何播放。

    MidiUtility provides low level MIDI features and you shouldn't typically need to use it directly. It provides some low level IO methods, byte swapping, and conversion of tempo/microtempo.

    MidiUtility提供了低级MIDI功能,您通常不需要直接使用它。 它提供了一些底层IO方法,字节交换和速度/微速度的转换。

    Note that to do things like set the tempo and time signature, you must add MidiMessageMeta messages for each to the corresponding tempo or time signature change. In most files, these should be added to track #0.

    请注意,要执行诸如设置速度和时间签名的操作,必须将每条消息的MidiMessageMeta消息添加到相应的速度或时间签名更改中。 在大多数文件中,这些文件应添加到轨道#0。

    局限性 (Limitations)

    • This library currently only works with Windows even though most of it is portable.

      该库当前仅适用于Windows,即使大多数库都是可移植的。
    • While it can read sysex messages from a file, it won't transmit them correctly.

      虽然它可以从文件中读取sysex消息,但无法正确传输它们。
    • It does not support SMPTE timing.

      它不支持SMPTE计时。
    • The loading and saving could be more robust in terms of handling corrupt files.

      就处理损坏的文件而言,加载和保存可能更加健壮。
    • FL Studio import for Track #0 doesn't seem to get fully recognized by FL Studio. I have yet to track down why. WMP seems to handle it fine, and FL does respect the timing and patch info so it doesn't seem to be a show stopper.

      曲目#0的FL Studio导入似乎没有被FL Studio完全识别。 我还没有找到原因。 WMP似乎可以很好地处理它,而FL确实尊重时间和补丁信息,因此它似乎不是秀场停止者。

    兴趣点 (Points of Interest)

    The Preview() methods do not use Win32 MCI "play" to play the file or sequence. Instead, the sequence is played on the calling thread using C# and calls to the MIDI device out Win32 API directly. Getting the timing right in that method was a total bear. You may want to dispatch it on a separate thread because it is CPU intensive. It's possible (maybe) to do this in a more CPU efficient manner by replacing the hard loop with a timer callback but that's not trivial to implement. See the demo code for the Preview thread handling.

    Preview()方法不使用Win32 MCI“播放”来播放文件或序列。 而是使用C#在调用线程上播放序列,并直接通过Win32 API调用MIDI设备。 用这种方法正确地把握时机完全是徒劳。 您可能希望将其分派到单独的线程上,因为它占用大量CPU。 可以(也许)通过将硬循环替换为计时器回调以更有效的CPU方式执行此操作,但这并非易事。 有关预览线程处理的信息,请参见演示代码。

    进一步阅读 (Further Reading)

    历史 (History)

    • 18th March, 2020 - Initial submission

      2020年3月18 -初次提交

    • 18th March, 2020 - Update 1: Added time signature support, bugfix in playback

      2020年3月18 -更新1:添加了拍号支持,并修复了播放中的错误

    • 18th March, 2020 - Update 2: Added several features to MidiSlicer and to the MIDI API

      2020年3月18 -更新2:为MidiSlicer和MIDI API添加了一些功能

    • 18th March, 2020 - Preview now loops.

      2020年3月18 -预览现在循环播放。

    • 20th March, 2020 - Added Normalize and Level scaling. Made the Offset and Length floating point

      2020年3月20 -添加了归一化和水平缩放。 制作偏移和长度浮点

    • 20th March, 2020 - Bugfix and improvement to Preview/SaveAs implementations

      2020年3月20 -修正和改进Preview / SaveAs实施

    • 21st March, 2020 - Improved timing in UI and of rendered tracks

      2020年3月21 -改进了UI和渲染轨道的时序

    • 22nd March, 2020 - Improved API, save, and preview

      3月22日2020年-改进的API,保存和预览

    • 22nd March, 2020 - Added Transpose() and Transpose GUI option

      3月22日2020年-增加移调()和移调GUI选项

    • 22nd March, 2020 - Added copyTimingAndPatchInfo option to GetRange() API methods

      3月22日2020年-增加copyTimingAndPatchInfo选项GetRange()API方法

    • 23rd March, 2020 - Improvements to API, and overal GUI functionality

      3月23日2020年-改进的API,并全部测试GUI功能

    翻译自: https://www.codeproject.com/Articles/5262538/A-MIDI-File-Slicer-and-MIDI-Library-in-Csharp

    c# midi播放器

    更多相关内容
  • MD_MIDIFile:标准MIDI文件(SMF)处理库
  • 概述RiffCrafter Studio使您可以使用MIDI文件可视化,播放,分析,创作和编辑音乐。 使用RiffCrafter Studio,您可以打开现有的MIDI文件或创建一个新的MIDI文件,然后使用鼠标,屏幕键盘,连接的MIDI设备甚至通过...
  • midi文件
  • midi-json-parser 该模块将midi文件解析为人类可读的JSON对象。 此模块解析二进制MIDI文件,并将其转换为JSON表示形式。 然后可以使用此JSON表示将其传递给 。 当然,也可以通过使用将其修改为再次编码为二进制MIDI...
  • 支持 MIDI 输出和 MIDI 文件 I/O。 Windows (Windows Multimedia)、Linux (ALSA)、Haiku (Midi Kit 2) 和 macOS (CoreMIDI) 支持 MIDI 输出。 MIDI 输出 QMidiOut类为系统的 MIDI 输出提供了一个接口。 /* ...
  • Midifile:C ++ MIDI文件解析库 Midifile是C ++类的库,用于读取/写入标准MIDI文件。 该库包含6个类: 处理MIDI文件的主界面。 MidiFile类显示为MidiEvents的二维数组:第一个维度是轨道列表,第二个维度是...
  • 中间数据MIDI文件的集合清洁程序在将数据上传到此处之前,首先(1)使用数据扫描为伪装成MIDI文件的非MIDI文件,然后(2)使用fdupes检查是否存在重复fdupes (这取决于文件的校验和,而不是文件名)。 。 通常,将...
  • 此应用程序可帮助您在播放MIDI文件或音频源的同时弹奏和即兴演奏和弦。 它通过更新滚动显示以将和弦音符映射到钢琴键盘来实现此目的。 它还可以为MIDI或PC键盘上的键动态分配音符或和弦。 同步是通过MIDI文件自动...
  • 乐谱是一种以印刷或手写制作,用符号来记录音乐的方法。不同的文化和地区发展了不同的记谱方法。记谱法可以分为记录音高和记录指法的两大类。五线谱和简谱都属于记录音高的乐谱。吉他的六线谱和古琴的减字谱都属于...
  • 制作音乐 MIDI 文件:midifich.mid,使用 MIDI1 规范。 您可以根据需要制作任意数量的音轨每个轨道需要一个矢量时间(增量时间),一个矢量间距,一个矢量速度。 新功能(23/09/2006): 弯音轮程序变更完整教程 ...
  • MidiKlavar是从MidiXml到其他文件格式的MIDI文件转换器。 MidiXml是由MusicXml.com(MusicXml文件格式背后的组织)管理的文件格式规范。 它与midi.org定义的MIDI二进制文件标准结合使用。 本质上,MidiXml使MIDI二...
  • 一、MIDI 文件简介、 二、MIDI 文件头解析、 1、MIDI 文件头标识、 2、MIDI 文件头长度、 3、MIDI 文件格式、 4、MIDI 轨道个数、 5、基本时间、





    一、MIDI 文件简介



    下面的 mid 文件是一个简单 midi , 其中只有一条轨道 , 一个音符 ;

    这个 mid 文件很简单 , 但是麻雀虽小 , 五脏俱全 , 其中有所有的必须的 midi 文件头 , midi 轨道头 , 时间标志 , 等信息 ;

    下面开始逐个字节 , 解析上述 midi 文件 ;

    4D 54 68 64 00 00 00 06 00 00 00 01 01 E0 4D 54 
    72 6B 00 00 00 25 00 FF 03 05 B2 E2 CA D4 30 00 
    FF 51 03 07 A1 20 00 FF 58 04 04 02 18 08 00 90 
    3C 64 8E 7E 80 3C 40 00 FF 2F 00
    

    在这里插入图片描述

    在这里插入图片描述





    二、MIDI 文件头解析



    文件头数据 :

    4D 54 68 64 00 00 00 06 00 00 00 01 01 E0
    

    在这里插入图片描述


    1、MIDI 文件头标识


    4D 54 68 64 : 0 ~ 3 字节 , " MThd " 字符串 ASCII 码 , 这是 mid 文件的标识 ;


    2、MIDI 文件头长度


    00 00 00 06 : 4 ~ 7 字节 , 这是个 4 字节整型数据 , 大端格式显示 , 整型低位在高字节 , 整型高位在低字节 , 该数据表示 mid 文件文件头长度 , 这里的文件头长度为 6 , 表示后面 6 字节是 mid 文件文件头的范围 ;

    在这里插入图片描述
    大端格式 : 高位存储在低字节中 , 符合人的书写习惯 ;

    在这里插入图片描述

    小端格式 : 低位存储在低字节中 , 符合计算机处理逻辑 ;

    在这里插入图片描述


    3、MIDI 文件格式


    00 00 : 8 ~ 9 字节 , 表示 mid 文件的格式 ; 这两个字节是 short 类型整型 , 大端格式 ;

    • 0 : mid 文件只有一条轨道 , 所有的通道都在一条轨道中 ;
    • 1 : mid 文件有多个音轨 , 并且是同步的 , 即所有的轨道同时播放 ;
    • 2 : mid 文件有多个音轨 , 不同步 ;

    这里是 0 格式 , 也就是说只有一条轨道 ;

    在这里插入图片描述


    4、MIDI 轨道个数


    00 01 : 10 ~ 11 字节 , 表示 MIDI 轨道个数 , short 类型 , 大端格式 ;

    此处表示有一条轨道 , 所有通道的音符和节拍信息都在该轨道中 ;

    在这里插入图片描述


    5、基本时间


    01 E0 : 12 ~ 13 字节 , 用于指定基本时间 ;

    2 个字节 , 要拆分成 3 部分 , 最高位 ( 第 15 位 ) 作为标识位 , 第 8 ~ 14 位 作为一部分 , 第 0 ~ 7 位 作为一部分 ;

    由于是大端格式排列 , mid 文件第 12 字节 ( 低地址 ) 是 高位 , mid 文件第 13 字节 ( 高地址 ) 是低位 ;

    01 E0 的二进制形式如下 : 0000 0001 11110 0000 ;

    最高位 0000 0001 11110 0000 是 0 , 红色的是最高位 , 表示当前 代表的事件格式是 类型1 , 第 0 ~ 14 位 代表的是 四分音符的 tick 数 ;

    十六进制 01 E0 对应的十进制数字是 480 , 也就是说一个四分音符有 480 tick ;

    tick 是时间单位 , 这是 mid 文件中计算时间的最基本单位 ;

    在这里插入图片描述

    展开全文
  • Midi 文件又好又小,但我不喜欢它们的声音…… Hydrogen 功能强大,非常适合在弹吉他时用作鼓机,但我懒得写下我想演奏的著名歌曲的节奏…… 解决方案 ? 中氢这是一个小型的 Python 脚本,可从 MIDI 文件的鼓通道...
  • 阅读器一个简单的零依赖 Java 库,用于从 Midi 文件读取事件。 MidiReader 类创建一个迭代器,它一次读取 Midi 文件中的所有轨道(对于同步多轨道文件)。 它将 Midi 事件混合成单个序列,以便按时间顺序检索事件。 ...
  • 米达尼用midi文件制作钢琴卷动画。依存关系需要Python> = 3.8 Python库:的OpenCVPython的美度其他: R绘制框架FFmpeg添加音频安装要在带有Homebrew的MacOS上安装R和FFmpeg,请执行以下操作: brew install rbrew ...
  • MIDI文件 npm install midi-file 解析器大致基于和 ,但是为了可移植性,它完全重写为使用数组而不是字符串。 用法 var fs = require ( 'fs' ) var parseMidi = require ( 'midi-file' ) . parseMidi var writeMidi ...
  • 模块化库,用于使用Go读取和写入MIDI消息和MIDI文件。 注意:如果您正在Github上阅读此文件,请注意,该存储库已移至Gitlab(gitlab.com/gomidi/midi),并且这只是一面镜子。 Go版本:> = 1.14 操作系统/体系...
  • MIDI文件唱歌合成该脚本依赖于名古屋工业大学的网站,该网站实现了基于HMM的唱歌声音合成系统。 您可以找到与乐器音频合并的样本。要求musescore:用于将midi转换为musicxml Python3安装pip install midi2voice...
  • 标准MIDI文件:读/写/播放 安装 npm install jzz-midi-smf --save 或bower install jzz-midi-smf 或yarn add jzz-midi-smf 或从获取完整的开发版本和缩小的脚本 用法 纯HTML < script src =" JZZ.js " > &...
  • 这是将MIDI文件转换为的项目的第一阶段。 最终目的是允许MIDI键盘用作输入设备,以生成定义曲调得分的格式正确的ABC文件。 这个阶段特别着重于Scandi风格的音乐,但仅针对输入本身进行了测试,该输入本身是计算机...
  • MIDI文件中的隐写术 隐写术正在研究技术的研究和应用,这些技术允许将消息或对象隐藏在其他被称为载体的内部,以使它们的存在不被察觉。 该脚本是用于学术目的。 该程序将消息隐藏在MIDI文件中。 MIDI文件中有事件...
  • 网络上带有MIDI文件的网站的精选列表。 内容 汇总集合 ,由收集和分类 ,档案 :指向专业和业余作曲家维护的网站的链接 MIDI链接,网页链接的集合,其中包含MIDI资料(midi文件,还有技术参考,说明等),作者是...
  • #MIDI 蜂鸣器MIDI beeper 是一个 Python 程序,它通过发出哔哔声来播放 MIDI 文件。 计算机的蜂鸣器而不是使用适当的声音电路。 如果你尝试玩和弦或复音,它会像旧的一样在交替音符之间快速切换办公室电话。 这听...
  • 现在越来越多的年轻人开始对MIDI制作感兴趣,特别是随着电脑的高速发展,原来离普通人很遥远的专业设备可以用软件代替,这无疑是音乐爱好者的福音,体验一下自己当音乐制作人的乐趣吧!那么什么是MIDI呢?MIDI是英语...

    现在越来越多的年轻人开始对MIDI制作感兴趣,特别是随着电脑的高速发展,原来离普通人很遥远的专业设备可以用软件代替,这无疑是音乐爱好者的福音,体验一下自己当音乐制作人的乐趣吧!

    那么什么是MIDI呢?MIDI是英语Music Instrument Digital Interface 的缩写,翻译过来就是“数字化乐器接口”,也就是说它的真正涵义是一个供不同设备进行信号传输的接口的名称。我们如今的MIDI音乐制作全都要靠这个接口,在这个接口之间传送的信息也就叫MIDI信息。

    下面我们就要触及MIDI音乐的实质了,很重要的!MIDI音乐是怎样制作出来的?它需要什么东西呢?其实MIDI音乐的制作过程中始终离不开三件“法宝”:音源音序器输入设备

    通俗地说,音源就是一个装了很多音色的东西,我们要听到音乐就必须靠它提供音色,不同的音源能提供不同的音色,当然就有好有坏,有高档和低档了。采样器实际上也是音源的一种,只不过它的音色不是固定的,而是来自于各类采样盘或是你自己采样。

    cda320f9-8814-eb11-8da9-e4434bdf6706.png

    但是音源其实也很笨,因为它自己不知道该在什么时候用什么音色发多长的音,它好比只是一个丰富的矿藏,至于如何利用不是音源的工作,必须有另一个设备来指挥它,这个设备就是MIDI制作的心脏―——音序器。音序器的任务就是记录下人的旨意,实际上就是记录了音乐的基本要素——速度,节奏,音色,音符的时值等等。这样在播放的过程中,音序器就会根据其内容指挥音源在什么时候用什么音色发多长的音,这样我们就能听到一首动听的歌曲了。

    至于输入设备也是很容易理解的,音序器的内容也得要人来告诉它呀!为了符合我们原有的演奏习惯,人们制造了许多基于传统乐器的MIDI输入设备,如MIDI键盘,MIDI吉它,MIDI吹管,MIDI小提琴等,我们可以按照演奏传统乐器的方法去演奏它们,而我们的演奏则通过MIDI OUT出口传送到音序器,被记录为音序内容。

    cfa320f9-8814-eb11-8da9-e4434bdf6706.png

    所以可以说MIDI文件的内容实际上就是音序内容,它只是一堆数字而已,大家如果在Cakewalk 这样的软件中打开Event list 所看到的东西就是MIDI音乐的内容了。所以MIDI文件的体积是很小的,一般只有几十KB,很适合在网络上传播。但正是因为MIDI文件不是以描述声音的波形为其记录形式的,所以同样的一个MIDI文件在不同的音源上播放效果会完全不一样,因为声音是靠音源发出的,而不同的声卡波表或硬件的音源音色都不一样。但是我们现在仍然可以从网上上下载MIDI音乐然后播放,也可以听啊,为什么呢?那完全是靠一个General MIDI(简称GM)的标准,通俗地理解它的意思就是把规定了128种常用乐器和控制器的排列顺序,例如所有的GM音色库第一号音色一定是三角钢琴,25号音色一定是钢弦吉它。只要大家都按GM标准制作音乐,使用GM音色库欣赏MIDI音乐,那么音色是不会错乱的,钢琴还是钢琴,吉它还是吉它,只不过各个音源的音色有区别。所以在网上提供的MIDI作品一定要符合GM标准。

    那么这“三大法宝”在我们生活中实际存在形式是怎样的呢?我们来分别看一下。

    音序器:分硬件和软件的两种。最早的是硬件音序器,我们也常称它为“编曲机”。它可以是一个独立的设备,也可以内置于合成器里。这类音序器的编辑和修改必须在它的面板上进行,使用是很不方便的。

    软件音序器当然要安装在电脑上,如我们常用的Cakewalk就是一个软件音序器。软件音序器因为其界面扩大(使用电脑显示器吗!),功能增强,特别是操作方便获得了绝大多数音乐制作者的认可,大有淘汰硬件音序器之势。其实正是由于软件加入音乐制作的领域才使MIDI音乐和电脑联系起来,不然制作MIDI音乐完全用不着电脑。大家要清楚不用电脑也可以制作MIDI音乐,使用电脑可以更方便地制作MIDI音乐,于是就产生了“电脑音乐”这个新名词,其实我们现在所说的电脑音乐并不是指让电脑来创造音乐,而是指在MIDI音乐的制作过程中用到了电脑和软件而已。

    音源:也分硬件和软件两种。硬件音源是现在专业MIDI制作不可缺少的设备,因为它们可以提供比任何一块声卡上的波表都要好很多的音色,这些独立音源基本上是专业人士使用的,如果你只是业余爱好的话就不需要添置这类设备,因为现在任何一块多媒体声卡上都有一个128种音色的GM音色库。另外,还可以使用软件音源来代替。软件音源也是随着电脑的高速发展而产生的,它们也必须安装在电脑上才能使用。软音源的产生为MIDI的大众化作出了很大的贡献,它使人们不需购买大量设备就可以在家中自得其乐了。

    输入设备:也有软件和硬件两种。不过这恐怕是唯一难以用软件代替的设备了,现在有各类虚拟电子琴和虚拟MIDI键盘,包括Cakewalk也带有一个Virtual Piano,但他们要么用鼠标点,要么用计算机键盘弹,这肯定是不惬意的,而且这样很难表现MIDI作品的细致性和人性。如果你想要制作出高水平的MIDI作品,输入设备还得要一个,我们一般用的都是MIDI键盘。所以就制作MIDI而言,会键盘演奏也是很重要哦!如果你实在什么乐器也不会,那只好采用软件音序器独具的功能:鼠标点击法!用鼠标点进音符也是输入音序内容的一种方法嘛,只不过苦了一点。

    d0a320f9-8814-eb11-8da9-e4434bdf6706.png

    上面讲了MIDI制作的基本知识,随着电脑的普及,越来越多的人开始从电脑了解了MIDI音乐,但是由于一些基础概念的不明确,导致对电脑音乐理解的错误。曾经听到这样说:Cakewalk的音色是挺好的……,这种说法是错误的,因为音色是由音源提供的,而Cakewalk只是一个软音序器,它是没有音色的。所以我们应该很清楚地了解我们制作MIDI音乐所用到的软件或硬件到底是属于哪个部分,如果某些关键性问题理解错了的话,在制作MIDI上就会遇到很多麻烦,还会导致重复投资或过度投资。

    (文章来源网络,如若涉及侵权请联系作者删除)

    展开全文
  • readmidi_java 允许您将 MIDI 文件的钢琴卷表示作为一系列音符。 writemidi_java 允许您写出钢琴卷。 那么为什么不直接使用原始的 Midi Toolbox 文件呢? 我的版本 (1) 在读取 midi 文件时正确解释速度变化,(2) ...
  • 一、MIDI 文件简介、 二、MIDI 文件头解析、 1、MIDI 文件头标识、 2、MIDI 文件头长度、 3、MIDI 文件格式、 4、MIDI 轨道个数、 5、基本时间、 三、MIDI 轨道分析、 四、MIDI 轨道头、 五、MIDI 轨道长度、 六、...





    一、MIDI 文件简介



    下面的 mid 文件是一个简单 midi , 其中只有一条轨道 , 一个音符 ;

    这个 mid 文件很简单 , 但是麻雀虽小 , 五脏俱全 , 其中有所有的必须的 midi 文件头 , midi 轨道头 , 时间标志 , 等信息 ;

    下面开始逐个字节 , 解析上述 midi 文件 ;

    4D 54 68 64 00 00 00 06 00 00 00 01 01 E0 4D 54 
    72 6B 00 00 00 25 00 FF 03 05 B2 E2 CA D4 30 00 
    FF 51 03 07 A1 20 00 FF 58 04 04 02 18 08 00 90 
    3C 64 8E 7E 80 3C 40 00 FF 2F 00
    

    在这里插入图片描述

    在这里插入图片描述





    二、MIDI 文件头解析



    文件头数据 :

    4D 54 68 64 00 00 00 06 00 00 00 01 01 E0
    

    在这里插入图片描述


    1、MIDI 文件头标识


    4D 54 68 64 : 0 ~ 3 字节 , " MThd " 字符串 ASCII 码 , 这是 mid 文件的标识 ;


    2、MIDI 文件头长度


    00 00 00 06 : 4 ~ 7 字节 , 这是个 4 字节整型数据 , 大端格式显示 , 整型低位在高字节 , 整型高位在低字节 , 该数据表示 mid 文件文件头长度 , 这里的文件头长度为 6 , 表示后面 6 字节是 mid 文件文件头的范围 ;

    在这里插入图片描述
    大端格式 : 高位存储在低字节中 , 符合人的书写习惯 ;

    在这里插入图片描述

    小端格式 : 低位存储在低字节中 , 符合计算机处理逻辑 ;

    在这里插入图片描述


    3、MIDI 文件格式


    00 00 : 8 ~ 9 字节 , 表示 mid 文件的格式 ; 这两个字节是 short 类型整型 , 大端格式 ;

    • 0 : mid 文件只有一条轨道 , 所有的通道都在一条轨道中 ;
    • 1 : mid 文件有多个音轨 , 并且是同步的 , 即所有的轨道同时播放 ;
    • 2 : mid 文件有多个音轨 , 不同步 ;

    这里是 0 格式 , 也就是说只有一条轨道 ;

    在这里插入图片描述


    4、MIDI 轨道个数


    00 01 : 10 ~ 11 字节 , 表示 MIDI 轨道个数 , short 类型 , 大端格式 ;

    此处表示有一条轨道 , 所有通道的音符和节拍信息都在该轨道中 ;

    在这里插入图片描述


    5、基本时间


    01 E0 : 12 ~ 13 字节 , 用于指定基本时间 ;

    2 个字节 , 要拆分成 3 部分 , 最高位 ( 第 15 位 ) 作为标识位 , 第 8 ~ 14 位 作为一部分 , 第 0 ~ 7 位 作为一部分 ;

    由于是大端格式排列 , mid 文件第 12 字节 ( 低地址 ) 是 高位 , mid 文件第 13 字节 ( 高地址 ) 是低位 ;

    01 E0 的二进制形式如下 : 0000 0001 11110 0000 ;

    最高位 0000 0001 11110 0000 是 0 , 红色的是最高位 , 表示当前 代表的事件格式是 类型1 , 第 0 ~ 14 位 代表的是 四分音符的 tick 数 ;

    十六进制 01 E0 对应的十进制数字是 480 , 也就是说一个四分音符有 480 tick ;

    tick 是时间单位 , 这是 mid 文件中计算时间的最基本单位 ;

    在这里插入图片描述







    三、MIDI 轨道分析



    MIDI 轨道 , 以 MTrk 4D 54 72 6B 开始 , 以 FF 2F 00 结束 ;

    下面的内容是一个完整的 MIDI 轨道二进制信息 ;

    4D 54 72 6B 00 00 00 25 00 FF 03 05 B2 E2 CA D4 30 00 FF 51 03 07 A1 20 00 FF 58 04 04 02 18 08 00 90 3C 64 8E 7E 80 3C 40 00 FF 2F 00
    

    在这里插入图片描述





    四、MIDI 轨道头



    4D 54 72 6B : MTrk 的 ASCII 码 ;

    在这里插入图片描述





    五、MIDI 轨道长度



    00 00 00 25 : 这是一个 int 类型的整型数据 , 大端格式显示 , midi 轨道长度是十六进制的 0x25 , 也就是十进制的 37 , 代表从下一个字节开始计数 到 轨道结束位置 FF 2F 00 的最后一个字节 , 一共有 37 个字节 ;

    每个轨道开始的标志是 MTrk , 后面的 4 字节就是轨道的长度 ;

    在这里插入图片描述

    在下图中 , 选中的字节有 37 37 37 个字节 ;

    在这里插入图片描述





    六、delta-time 间隔



    delta-time 间隔 是 mid 中的重要机制 ;

    midi 中的音符 , 事件 的时间间隔 , 都是通过 delta-time 体现的 ;

    delta-time 是一个整数 , 位数不固定 , 其单位是 tick , 也就是 【BLE MIDI】MIDI 文件格式分析 ( MIDI 文件头解析 | MIDI 文件头标识 | MIDI 文件头长度 | MIDI 文件格式 | MIDI 轨道个数 | 基本时间 ) 二、MIDI 文件头解析 5、基本时间 博客章节中计算的 tick 时间 ;

    delta-time 的每个字节中 , 最高位 第 7 位 用于表示连续标志 , 后面的 0 ~ 6 位 表示真实的数据 ;

    如果一个 delta-time 由 2 字节组成 , 每个字节中最高位是连续标志 , 后面 0 ~ 6 位是数据 , 也就是说该 delta-time 实际的数值位数只有 14 位 ;

    以后面的 8E 7E delta-time 为例 :

    在这里插入图片描述

    8E 7E 对应的二进制位数为 : 1000 1110 0111 1110

    第一个字节 8E 对应的二进制数据位 1000 1110 , 其中第七位的 1 表示这是 delta-time 的高位字节 , 后面的 000 1110 是实际的数值数据 ;

    第一个字节 7E 对应的二进制数据位 0111 1110 , 其中第七位的 0 表示这是 delta-time 的低位字节 , 后面的 111 1110 是实际的数值数据 ;

    则该 delta-time 的实际数据是 000 1110 111 1110 , 重新组合后为 111 0111 1110 , 该 delta-time 的值是 1918 , 也就是 1918 个 tick 数 ;

    在这里插入图片描述


    82 C0 03 为例 , 对应的二进制数据为 1000 0010 1100 0000 0000 0011

    第一个字节 82 对应的二进制数据位 1000 0010 , 其中第七位的 1 表示这是 delta-time 的高位字节 , 后面的 000 0010 是实际的数值数据 ;

    第二个字节 C0 对应的二进制数据位 1100 0000 , 其中第七位的 1 表示这是 delta-time 的高位字节 , 后面的 100 0000 是实际的数值数据 ;

    第三个字节 03 对应的二进制数据位 0000 0011 , 其中第七位的 0 表示这是 delta-time 的低位字节 , 后面的 000 0011 是实际的数值数据 ;

    则该 delta-time 的实际数据是 000 0010 100 0000 000 0011 , 重新组合后为 1010 0000 0000 0011 , 该 delta-time 的值是 40963 , 也就是 40963 个 tick 数 ;

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述





    七、FF 03 轨道名称



    FF 03 05 B2 E2 CA D4 30 : 23 ~ 30 字节 , FF 03 是 Meta 事件 , 轨道名称设置 ;

    FF 03 后面是长度信息 , 05 表示该轨道名称有 5 字节 , 后面的 5 字节就是轨道名称 ;

    在这里插入图片描述
    轨道信息后面的 31 字节 00 是 delta-time ;





    八、FF 51 03 四分音符时长



    FF 51 03 07 A1 20 : 32 ~ 37 字节 , 音符速度标志 ;

    FF 51 03 是音符速度标志位 , 后面的 07 A1 20 3 字节是一个数字 , 代表 四分音符 的时长 , 单位是微秒 ;

    在这里插入图片描述

    07 A1 20 对应十进制数是 500000 , 五十万 , 也就是一个四分音符是 50 万微秒 ;

    在这里插入图片描述

    在之前的 【BLE MIDI】MIDI 文件格式分析 ( MIDI 文件头解析 | MIDI 文件头标识 | MIDI 文件头长度 | MIDI 文件格式 | MIDI 轨道个数 | 基本时间 ) 二、MIDI 文件头解析 5、基本时间 博客章节 解析到一个四分音符有 480 个 tick ;

    此时可以计算出每个 tick 的时长为 500000 480 \cfrac{500000}{480} 480500000 微秒 ;

    在这里插入图片描述

    再回顾下 delta-time 的计算 :

    8E 7E 对应的二进制位数为 : 1000 1110 0111 1110

    第一个字节 8E 对应的二进制数据位 1000 1110 , 其中第七位的 1 表示这是 delta-time 的高位字节 , 后面的 000 1110 是实际的数值数据 ;

    第一个字节 7E 对应的二进制数据位 0111 1110 , 其中第七位的 0 表示这是 delta-time 的低位字节 , 后面的 111 1110 是实际的数值数据 ;

    则该 delta-time 的实际数据是 000 1110 111 1110 , 重新组合后为 111 0111 1110 , 该 delta-time 的值是 1918 , 也就是 1918 个 tick 数 ;

    上述的 delta-time 是 1918 个 tick , 对应的时间是 500000 × 1918 480 \cfrac{500000 \times 1918}{480} 480500000×1918 微秒





    九、FF 58 04 拍号



    FF 58 04 04 02 18 08 : 39 ~ 45 字节 , 拍子记号 ;

    FF 58 04 是拍子记号的标志 ;

    04 02 18 08 分别表示 :

    • 04 : 拍子记号的分子 ;
    • 02 : 拍子记号分母标志 , 这里的值是 2 的次幂值 , 如当前设置的值是 2 , 则拍子记号的分母是 2 2 = 4 2^2 = 4 22=4 , 分母是 4 ;
    • 18 : 每个 MIDI 时钟包含的 tick 数 ; 标准值是 24 , 一般不会改变 ;
    • 08 : 每 24 个 MIDI 时钟 , 对应的 32 分音符的数目 ; 标准值是 8 , 一般不会改变 ;

    在这里插入图片描述

    后面的 00 是 delta-time , 与下一个 midi 事件间隔的 tick 数 ;

    delta-time 参考 【BLE MIDI】MIDI 文件格式分析 ( MIDI 轨道分析 | MIDI 轨道头 | MIDI 轨道长度 | delta-time 间隔 ) 四、delta-time 间隔 博客章节 ;





    十、音符开指令



    90 3C 64 : 47 ~ 49 字节 , 音符开指令 ;

    90 是音符开标志 ;

    3C 是音符音高 60 , 取值范围 0 ~ 127 ;

    64 是音符的力度值 , 取值范围 0 ~ 127 ;

    在这里插入图片描述

    后面的 8E 7E 是 delta-time , 与后面的指令间隔的 tick 数 ;

    delta-time 参考 【BLE MIDI】MIDI 文件格式分析 ( MIDI 轨道分析 | MIDI 轨道头 | MIDI 轨道长度 | delta-time 间隔 ) 四、delta-time 间隔 博客章节 ;





    十一、音符关指令



    80 3C 40 : 52 ~ 54 字节 , 音符关指令 ;

    80 是音符开标志 ;

    3C 是音符音高 60 , 取值范围 0 ~ 127 ;

    40 是音符的力度值 , 取值范围 0 ~ 127 ;

    在这里插入图片描述

    后面的 00 是 delta-time , 与后面的指令间隔的 tick 数 ;

    delta-time 参考 【BLE MIDI】MIDI 文件格式分析 ( MIDI 轨道分析 | MIDI 轨道头 | MIDI 轨道长度 | delta-time 间隔 ) 四、delta-time 间隔 博客章节 ;





    十二、音轨结束标志



    FF 2F 00 : 56 ~ 58 字节 , 音轨结束标识 ;

    在这里插入图片描述

    至此 , 整个 midi 文件解析完毕 ;

    展开全文
  • iOS版本midi文件解析工具类,C语言封装,非常好用,很详细,有需要的可以直接下载使用,拖入工程即可使用
  • #XMIDI###简介XMIDI是一款IOS上的MIDI文件播放引擎,基于Audio Toolbox Framework和OpenAL这两个库。 XMIDI使用Audio Toolbox Framework下API来完成MIDI文件的读取和解析,然后使用OpenAL来播放对应的音符。OpenAL...
  • 迷笛歌词安装将此行添加到应用程序的 Gemfile 中: gem 'midi_lyrics'然后执行: $ bundle或者自己安装: $ gem install midi_lyrics用法 >> MidiLyrics::Parser.new("test.mid").extract=> [ { text: "Test", start...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,507
精华内容 10,202
关键字:

如何制作midi文件

友情链接: exam.rar.rar