标准的MIDI文件格式就像奇异的兽。总体看来,它是那样的让你无法抗拒。当然,你怎样看它无关紧要,可是用足够多的描述符描述一段音乐并使它能够重现,可不是很少的工作就可以完成的。然而,它虽然复杂,但是真正理解之后,MIDI文件格式的结构还是很直观明了的。

在这里我必须放弃一些东西,因为毕竟我不是MIDI也不是MIDI文件专家!最近我为我的PC准备了一块Gravis 超音频音效卡,利用它听完几段MIDI文件(.mid)之后,想:“呵,我要是能够制作自己的MIDI(.mid)文件该多好啊!”嗯,经过烦人的几个小时之后,我发现,那些并不是没有价值的工作。但是,我是不会让一个冗长的文件格式就能够阻止的(此外,我告诉过我的妻子,计算机不是很难用的,而且我十分憎恨当一个伪君子)。那么,在这篇文章中如果发现什么错误,请让我知道,我会修改它的。同时,这份文档的范围并没有提供所有类型的MIDI命令和任何可能的文件配置!这篇基本指南将使读者能够(以中等的时间投资)制作出MIDI类型的文件。

1.概述:

一个MIDI文件基本上由两个部分组成,头块和轨道块。第二节讲述头块,第三节讲述轨道块。一个MIDI文件有一个头块用来描述文件的格式、许多的轨道块等内容。一个轨道可以想象为像一个大型多音轨录音机那样,你可以为某种声音、某种乐谱、某种乐器或者你需要的任何东西分配一个轨道。

2.头块:

头块出现在文件的开头,有三种方式来描述文件。头块看起来一直是这样的:
4D 54 68 64 00 00 00 06 ff ff nn nn dd dd

前4个字节等同于ASCII码MThd,接着MThd之后的4个字节是头的大小。它将一直是00 00 00 00 06,因为现行的头信息将一直是6字节。

ff ff是文件的格式,有3种格式:
0-单轨
1-多规,同步
2-多规,异步

单轨,很显然就只有一个轨道。同步多轨意味着所有轨道都是垂直同步的,或者其他的措辞为他们都在同一时间开始,并且可以表现一首歌的不同部分。异步多轨没有必要同时开始,而且可以完全的不同步。

nn nn 是MIDI文件中的轨道数。
dd dd 是每个4分音符delta-time节奏数(这之后将做详细介绍)。

3.轨道块:

头块之后剩下的文件部分是轨道块。每一个轨道包含一个头,并且可以包含你所希望的许多MIDI命令。轨道头与文件头及其相似:

4D 54 72 6B xx xx xx xx

与头一致,前4个字节是ASCII吗,这个是MTrk,紧跟MTrk的4个字节给出了以字节为单位的轨道的长度(不包括轨道头)。

在头之下是MIDI事件,这些事件同现行的可以被带有累加的MIDI合成器端口接受和发送的数据是相同的。一个MIDI 事件先于一个delta-time。一个delta-time是一个MIDI事件被执行后的节奏数,每个四分之一音符的节奏数先前已经定义在了文件的头块中。这个delta-time是一个可变长度的编码值。这种格式虽然混乱,可是允许根据需要利用多位表示较大的数值,这不会因为需求小的数值情况下以添零的方式浪费掉一些字节!数值被转换为7位的字节,并且除了最后一个字节以最高有效位是0外,各个字节最有意义的一位是1,。这就允许一个数值被一次一个字节地读取,你如果发现最高有效位是0,则这就是这个数值的最后一位(意义比较小)。依照MIDI说明,全部delta-time的长度最多超过4字节。

delta-time 之后就是MIDI事件,每个MIDI事件(除了正在运行的事件外)带有一个最高有效位总是1的命令字节(值将>128)。大部分命令的列表在附录A中。每个命令都有不同的参数和长度,但是接下来的数据将是最高有效位为零(值将<128)。这里有个例外就是meta-event,最高有效位可以是1。然而,meta-events需要一个长的参数以区分。

微小失误就可以导致混乱的是运行模式,这是现行MIDI命令所忽略的地方,并且最终发行的MIDI命令是假定的。这就意味这如果包含了命令,那么MIDI事件就是由delta-time与参数组成而转换的。

4.综述:

如果这份说明仅仅是使问题更加混乱,那么以下提供的例子可能有助于澄清问题!同时,两个公用程序和一个图解文件包含在这个文档里面:

DEC.EXE——这个公共程序是将二进制文件(比如.MID)转换成以十进制表示的对应每个字节的有标记界限的文本文件。

REC.EXE——这个公共程序是将有标记界限的十进制数文本文件对应的每一字节转换成二进制文件。

MIDINOTE.PS——这是一个对应键盘和五线谱的音符数字附录页。

附录A

1.MIDI事件命令

每个命令字节有两部分,左nybble(4位)包含现行的命令,右nybble包含将被执行的命令的通道号,这里有16各MIDI通道8个MIDI命令(命令nybble必须最高有效位是1的)。在下表中,X表示MIDI通道号。所有的音符即数据字节都<128(最高有效位是0)。

十六进制 二进制 数据 描述

8x      1000xxxx    nn vv        音符关闭 (释放键盘)
                            nn=音符号
                            vv=速度

9x      1001xxxx    nn vv        音符打开 (按下键盘)
                            nn=音符号
                            vv=速度

Ax      1010xxxx    nn vv        触摸键盘以后
                            nn=音符号
                            vv=速度

Bx      1011xxxx    cc vv        调换控制
                            cc=控制号
                            vv=新值

Cx      1100xxxx    pp            改变程序(片断)
                            pp=新的程序号

Dx      1101xxxx    cc            在通道后接触
cc=管道号

Ex      1110xxxx    bb tt        改变互相咬和的齿轮 (2000H 表明缺省或没有改变)(什么意思搞不懂:)
                            bb=值的低7位(least sig) 
                             tt=值的高7位 (most sig)

下表是没有通道的 meta-events列表 ,他们的格式是:

FF xx nn dd

所有的 meta-events 是以 FF 开头的命令 (xx),长度,或者含在数据的字节数(nn),现行的数据(dd)

十六进制 二进制 数据 描述
00      00000000    nn ssss      设定轨道的序号
                            nn=02 (两字节长度的序号)
                            ssss=序号

01      00000001    nn tt ..      你需要的所有文本事件
                        nn=以字节为单位的文本长度
                            tt=文本字符

02      00000010    nn tt ..      同文本的事件, 但是用于版权信息
                           nn tt=同文本事件

03      00000011  nn tt ..      序列或者轨道名
                         nn tt=同文本事件

04      00000100    nn tt ..      轨道乐器名
                            nn tt=同文本事件

05      00000101    nn tt ..      歌词
                            nn tt=同文本事件

06      00000110    nn tt ..      标签
                            nn tt=同文本事件

07      00000111    nn tt ..      浮点音符
                           nn tt=同文本事件

2F      00101111    00            这个事件一定在每个轨道的结尾出现

51      01010001    03 tttttt    设定拍子
                                tttttt=微秒/四分音符

58      01011000    04 nn dd cc bb 拍子记号
                                nn=拍子记号分子
                                dd=拍子记号分母2=四分之一
                                3=8分拍, 等等.
                                cc=节拍器的节奏
                                bb=对四分之一音符标注的第32号数字

59    01011001    02 sf mi      音调符号
                              sf=升调/降调(-7=7 降调, 0=基准C调,7=7 升调)
                              mi=大调/小调(0=大调, 1=小调)

7F      01111111    xx dd ..      音序器的详细信息
                            xx=被发送的字节数
                            dd=数据

下表列出了控制整个系统的系统消息。这里没有MIDI通道数 (这些一般仅应用于MIDI键盘等.)

十六进制      二进制  数据          描述

F8      11111000                  同步所必须的计时器
FA      11111010                  开始当前的队列
FB      11111011                  从停止的地方继续一个队列
FC      11111100                  停止一个队列

下表列出的是与音符相对应的命令标记。
八度音阶¦¦                    音符号
  #  ¦¦
      ¦¦ C   ¦ C#  ¦ D    ¦ D#   ¦ E   ¦ F    ¦ F#   ¦ G   ¦ G#   ¦ A   ¦ A#   ¦ B
-----------------------------------------------------------------------------
  0  ¦¦  0  ¦  1  ¦  2  ¦  3  ¦  4  ¦  5  ¦  6  ¦  7  ¦  8  ¦  9  ¦  10 ¦ 11
  1  ¦¦  12 ¦  13 ¦  14 ¦  15 ¦  16 ¦  17 ¦  18 ¦  19 ¦  20 ¦  21 ¦  22 ¦ 23
  2  ¦¦  24 ¦  25 ¦  26 ¦  27 ¦  28 ¦  29 ¦  30 ¦  31 ¦  32 ¦  33 ¦  34 ¦ 35
  3  ¦¦  36 ¦  37 ¦  38 ¦  39 ¦  40 ¦  41 ¦  42 ¦  43 ¦  44 ¦  45 ¦  46 ¦ 47
  4  ¦¦  48 ¦  49 ¦  50 ¦  51 ¦  52 ¦  53 ¦  54 ¦  55 ¦  56 ¦  57 ¦  58 ¦ 59
  5  ¦¦  60 ¦  61 ¦  62 ¦  63 ¦  64 ¦  65 ¦  66 ¦  67 ¦  68 ¦  69 ¦  70 ¦ 71
  6  ¦¦  72 ¦  73 ¦  74 ¦  75 ¦  76 ¦  77 ¦  78 ¦  79 ¦  80 ¦  81 ¦  82 ¦ 83
  7  ¦¦  84 ¦  85 ¦  86 ¦  87 ¦  88 ¦  89 ¦  90 ¦  91 ¦  92 ¦  93 ¦  94 ¦ 95
  8  ¦¦  96 ¦  97 ¦  98 ¦  99 ¦ 100 ¦ 101  ¦ 102  ¦ 103 ¦  104 ¦ 105 ¦ 106  ¦ 107
  9  ¦¦ 108 ¦ 109  ¦ 110 ¦  111 ¦ 112 ¦ 113 ¦ 114 ¦ 115 ¦ 116 ¦ 117 ¦ 118 ¦ 119
  10 ¦¦ 120 ¦ 121  ¦ 122 ¦  123 ¦ 124 ¦ 125 ¦ 126 ¦ 127 ¦

参考资料:
"MIDI Systems and Control" Francis Rumsey  1990 Focal Press
"MIDI and Sound Book for the Atari ST" Bernd Enders and Wolfgang Klem 1989 M&T Publishing, Inc.
MIDI file specs and general MIDI specs were also obtained by sending e-mail to LISTSERV@AUVM.AMERICAN.EDU with the phrase GET MIDISPEC PACKAGE in the message.
------------------------------ DEC.CPP ------------------------------------

/*  file  dec.cpp

by  Dustin Caldwell    (dustin@gse.utah.edu)

*/

#include <dos.h>
#include <stdio.h>
#include <stdlib.h>

void helpdoc();

main()
{
        FILE *fp;

unsigned char ch, c;

if((fp=fopen(_argv[1], "rb"))==NULL)            /* open file to read */
        {
                printf("cannot open file %s/n",_argv[1]);
                helpdoc();
                exit(-1);
        }

c=0;
        ch=fgetc(fp);

while(!feof(fp))                        /* loop for whole file */
        {
                printf("%u/t", ch);            /* print every byte's decimal equiv. */
                c++;
                if(c>8)                                /* print 8 numbers to a line */
                {
                        c=0;
                        printf("/n");
                }

ch=fgetc(fp);
        }

fclose(fp);                    /* close up */
}

void helpdoc()                  /* print help message */
{
        printf("/n  Binary File Decoder/n/n");

printf("/n Syntax:  dec binary_file_name/n/n");

printf("by Dustin Caldwell  (dustin@gse.utah.edu)/n/n");
        printf("This is a filter program that reads a binary file/n");
        printf("and prints the decimal equivalent of each byte/n");
        printf("tab-separated. This is mostly useful when piped /n");
        printf("into another file to be edited manually.  eg:/n/n");
        printf("c:/>dec sonata3.mid > son3.txt/n/n");
        printf("This will create a file called son3.txt which can/n");
        printf("be edited with any ascii editor. /n/n");
        printf("(rec.exe may also be useful, as it reencodes the /n");
        printf("ascii text file)./n/n");
        printf("Have Fun!!/n");
}

---------------------------- REC.CPP ----------------------------------

/*  File  rec.cpp
        by Dustin Caldwell  (dustin@gse.utah.edu)
*/

#include <dos.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

void helpdoc();

main()
{
        FILE *rfp, *wfp;

unsigned char ch, c;
        char s[20];

if((rfp=fopen(_argv[1], "r"))==NULL)                    /* open the read file */
        {
                printf("cannot open file %s /n",_argv[1]);
                helpdoc();
                exit(-1);
        }

if((wfp=fopen(_argv[2], "wb"))==NULL)                  /* open the write file */
        {
                printf("cannot open file %s /n",_argv[1]);
                helpdoc();
                exit(-1);
        }

c=0;

ch=fgetc(rfp);

while(!feof(rfp))                      /* loop for whole file */
        {

if(isalnum(ch))                /* only 'see' valid ascii chars */
                {
                        c=0;
                        while(isdigit(ch))      /* only use decimal digits (0-9) */
                        {
                                s[c]=ch;        /* build a string containing the number */
                                c++;
                                ch=fgetc(rfp);
                        }
                        s[c]=NULL;                      /* must have NULL terminator */

fputc(atoi(s), wfp);/* write the binary equivalent to file */

}

ch=fgetc(rfp);                  /* loop until next number starts */

}

fclose(rfp);                    /* close up */
        fclose(wfp);
}

void helpdoc()          /* print help message */
{
        printf("/n  Text File Encoder/n/n");

printf("/n Syntax:  rec text_file_name binary_file_name/n/n");

printf("by Dustin Caldwell  (dustin@gse.utah.edu)/n/n");
        printf("This is a program that reads an ascii tab-/n");
        printf("delimited file and builds a binary file where/n");
        printf("each byte of the binary file is one of the decimal/n");
        printf("digits in the text file./n");
        printf(" eg:/n/n");
        printf("c:/>rec son3.txt son3.mid/n/n");
        printf("(This will create a file called son3.mid which is/n");
        printf("a valid binary file)/n/n");
        printf("(dec.exe may also be useful, as it decodes binary files)/n/n");
        printf("Have Fun!!/n");
}

[C/C++]标准MIDI文件格式相关推荐

  1. 标准MIDI文件格式规范。 1.1(机翻)

    0-简介 本文档概述了MIDI文件的规范. MIDI文件的目的是提供一种在相同或不同计算机上的不同程序之间交换带时间戳的MIDI数据的方法.主要设计目标之一是紧凑表示,这使其非常适合基于磁盘的文件格式 ...

  2. 音乐研发必备:理解 MIDI 协议与标准 MIDI 文件格式

    动手点关注 干货不迷路 

  3. MIDI 文件格式 (转)

    MIDI 文件格式 (转)[@more@] MIDI 文件格式 MIDI 文件结构 Chunks MIDI 文件由 chunks 组成:XML:namespace prefix = o ns = &q ...

  4. MIDI文件格式分析(补充和勘误)

    MIDI文件格式分析(补充和勘误) 本文是对<MIDI文件格式分析>博客链接的一点补充: 原文复制 vim编辑二进制文件的方法 文中制作的midi文件内容和改动 原文复制 MIDI文件属于 ...

  5. MIDI 文件格式分析

    MIDI 文件属于二进制文件,这种文件一般都有如下基本结构: 文件头+数据描述 文件头一般包括文件的类型,因为 Midi 文件仅以.mid 为扩展名的就有 0 类和 1 类两种,而大家熟悉的位 图文件 ...

  6. MIDI文件格式解析

    乐器数字接口MIDI(Musical Instrument Digital Interface)是数字音乐国际的标准,定义了计算机音乐程序.合成器及其他电子设备交换信息和电子信号的方式,解决不同电子乐 ...

  7. 【BLE MIDI】MIDI 文件格式分析总结 ★★★

    文章目录 一.MIDI 文件简介 二.MIDI 文件头解析 1.MIDI 文件头标识 2.MIDI 文件头长度 3.MIDI 文件格式 4.MIDI 轨道个数 5.基本时间 三.MIDI 轨道分析 四 ...

  8. 【BLE MIDI】MIDI 文件格式分析 ( FF 58 04 拍号 | 音符开指令 | 音符关指令 | 音轨结束标志 )

    文章目录 前言 一.FF 58 04 拍号 二.音符开指令 三.音符关指令 四.音轨结束标志 前言 在博客 [BLE MIDI]MIDI 文件格式分析 ( MIDI 文件头解析 | MIDI 文件头标 ...

  9. 【BLE MIDI】MIDI 文件格式分析 ( FF 03 轨道名称 | FF 51 03 四分音符时长 )

    文章目录 前言 一.FF 03 轨道名称 二.FF 51 03 四分音符时长 前言 在博客 [BLE MIDI]MIDI 文件格式分析 ( MIDI 文件头解析 | MIDI 文件头标识 | MIDI ...

  10. 【BLE MIDI】MIDI 文件格式分析 ( MIDI 轨道分析 | MIDI 轨道头 | MIDI 轨道长度 | delta-time 间隔 )

    文章目录 前言 一.MIDI 轨道分析 二.MIDI 轨道头 三.MIDI 轨道长度 四.delta-time 间隔 前言 上一篇博客 [BLE MIDI]MIDI 文件格式分析 ( MIDI 文件头 ...

最新文章

  1. python3 x完全兼容_【转】Python3.x与Python2.x的主要区别 (O_O )?
  2. 本蒟蒻对于二分图一些定理的理解
  3. php函数文件,PHP文件函数大全
  4. Javascript中使用正则表达式进行数据验证
  5. 如何把Linux工具里的“军刀”BusyBox移植到RT-Thread Smart?
  6. Android之Fragment(一)
  7. 在ArcEngine中使用Geoprocessing工具-执行工具
  8. Spring异步任务处理,@Async的配置和使用
  9. 初识Hadoop(核心组件与应用)
  10. STM32 USB接口 一键下载电路详解与过程分析
  11. oracle优化之driving_site
  12. Linux 学习之路(一)——Linux 发行版本的选择以及opensuse 13.1 安装
  13. 2020中兴捧月算法大赛参赛总结
  14. ps怎么加底部阴影_PS给物体底部加阴影
  15. windows环境下搭建ftp服务和web服务,实现图片服务器功能
  16. 使用pt-stalk诊断MySQL问题
  17. 视频点播播放器如何实现加密下载?
  18. 全球重磁异常以及水深数据分享
  19. 《口算大作战 概念版》功能规格说明书
  20. 2022年,你的数据库还没有上云吗?

热门文章

  1. 为什么阿里巴巴不建议MySQL使用Text类型?
  2. 一位 中国70 后老程序员的 26 个职场感悟
  3. 在html中调用js函数
  4. 我对计算机基础的认识,我对计算机的认识
  5. linux版 3d建模软件,3D建模软件(Meshroom)
  6. JAVA,OpenCV简单实现“全能扫描王”的功能
  7. 键盘连接计算机接口,终于明白电脑如何连接键盘
  8. 【艾特淘】淘宝流量黄金标题的制作方法本
  9. 使用HTML5仿制的QQ音乐PC版界面
  10. mac系统安装win10双系统