2007年11月15日星期四

FW: [嘻嘻哈哈] 标准MIDI文件格式

标准MIDI文件格式  
  达思挺・考德威尔  
   
   
  标准的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.  


--
由 Pegasus 于 11/12/2007 11:26:00 下午 在 嘻嘻哈哈 上发表

2007年11月13日星期二

C++编译中经常遇到的错误

C++编译中经常遇到的错误
 
 
1、fatal error C1010: unexpected end of
file while looking for precompiled header directive。
 

寻找预编译头文件路径时遇到了不该遇到的文件尾。(一般是没有#include
"stdafx.h")
 
2、fatal error C1083: Cannot open
include file: 'R…….h': No such file or directory
 

不能打开包含文件"R…….h":没有这样的文件或目录。
 
3、error C2011: 'C……': 'class' type
redefinition
 
类"C……"重定义。
 
4、error C2018: unknown character
'0xa3'
 

不认识的字符'0xa3'。(一般是汉字或中文标点符号)
 
5、error C2057: expected constant
expression
 

希望是常量表达式。(一般出现在switch语句的case分支中)
 
6、error C2065: 'IDD_MYDIALOG' :
undeclared identifier
 

"IDD_MYDIALOG":未声明过的标识符。
 
7、error C2082: redefinition of formal
parameter 'bReset'
 

函数参数"bReset"在函数体中重定义。
 
8、error C2143: syntax error: missing
':' before '{'
 
句法错误:"{"前缺少";"。
 
9、error C2146: syntax error : missing
';' before identifier 'dc'
 
句法错误:在"dc"前丢了";"。
 
10、error C2196: case value '69'
already used
 

值69已经用过。(一般出现在switch语句的case分支中)
 
11、error C2509: 'OnTimer' : member
function not declared in 'CHelloView'
 

成员函数"OnTimer"没有在"CHelloView"中声明。
 
12、error C2511: 'reset': overloaded
member function 'void (int)' not found in 'B'
 
重载的函数"void
reset(int)"在类"B"中找不到。
 
13、error C2555: 'B::f1': overriding
virtual function differs from 'A::f1' only by return type or
calling convention
 

类B对类A中同名函数f1的重载仅根据返回值或调用约定上的区别。
 
14、error C2660: 'SetTimer' : function
does not take 2 parameters
 
"SetTimer"函数不传递2个参数。
 
15、warning C4035: 'f……': no return
value
 
"f……"的return语句没有返回值。
 
16、warning C4553: '= =' : operator has
no effect; did you intend '='?
 
没有效果的运算符"=
=";是否改为"="?
 
17、warning C4700: local variable
'bReset' used without having been initialized
 

局部变量"bReset"没有初始化就使用。
 
18、error C4716: 'CMyApp::InitInstance'
: must return a value
 

"CMyApp::InitInstance"函数必须返回一个值。
 
19、LINK : fatal error LNK1168: cannot
open Debug/P1.exe for writing
 

连接错误:不能打开P1.exe文件,以改写内容。(一般是P1.Exe还在运行,未关闭)
 
20、error LNK2001: unresolved external
symbol "public: virtual _ _thiscall C……::~C……(void)"
 

连接时发现没有实现的外部符号(变量、函数等)。
 
Best Regards
Miao Jia Hong
 

MIDI编曲

MIDI编曲
低阶MIDI的API包括字首为midiIn和midiOut的函式,它们分别用於读取来自外部控制器的MIDI序列和在内部或外部的合成器上播放音乐。尽管其名称为「低阶」,但使用这些函式时并不需要了解MIDI卡上的硬体介面。

要在播放音乐的准备期间打开一个MIDI输出设备,可以呼叫midiOutOpen函式:

error = midiOutOpen (&hMidiOut, wDeviceID, dwCallBack,
                             dwCallBackData, dwFlags) ;
如果呼叫成功,则函式传回0,否则传回错误代码。如果参数设定正确,则常见的一种错误就是MIDI设备已被其他程式使用。

该函式的第一个参数是指向HMIDIOUT型态变数的指标,它接收後面用於MIDI输出函式的MIDI输出代号。第二个参数是设备ID。要使用真实的 MIDI设备,这个参数范围可以是从0到小於由midiOutGetNumDevs传回的数值。您还可以使用MIDIMAPPER,它在 MMSYSTEM.H中定义为-1。大多数情况下,函式的後三个参数设定为NULL或0。

一旦打开一个MIDI输出设备并获得了其代号,您就可以向该设备发送MIDI讯息。此时可以呼叫:

error = midiOutShortMsg (hMidiOut, dwMessage) ;
第一个参数是从midiOutOpen函式获得的代号。第二个参数是包装在32位元DWORD中的1位元组、2位元组或者3位元组的讯息。我在前面讨论过,MIDI讯息以状态位元组开始,後面是0、1或2位元组的资料。在dwMessage中,状态位元组是最不重要的,第一个资料位元组次之,第二个资料位元组再次之,最重要的位元组是0。

例如,要在MIDI通道5上以0x7F的速度演奏中音C(音符是0x3C),则需要3位元组的Note On讯息:

0x95 0x3C 0x7F
midiOutShortMsg的参数dwMessage等于0x007F3C95。

三个基础的MIDI讯息是Program Change(可为某一特定通道而改变乐器声音)、Note On和Note Off。打开一个MIDI输出设备後,应该从一条Program Change讯息开始,然後发送相同数量的Note On和Note Off讯息。

当您一直演奏您想演奏的音乐时,您可以重置MIDI输出设备以确保关闭所有的音符:

midiOutReset (hMidiOut) ;
然後关闭设备:

midiOutClose (hMidiOut) ;
使用低阶的MIDI输出API时,midiOutOpen、midiOutShortMsg、midiOutReset和midiOutClose是您需要的四个基础函式。

现在让我们演奏一段音乐。BACHTOCC,如程式22-8所示,演奏了J. S. Bach著名的风琴演奏的D小调《Toccata and Fugue》中托卡塔部分的第一小节。

2007年11月11日星期日

Standard MIDI File Format


                                                        Standard   MIDI   File   Format  
                                                                  Dustin   Caldwell  
   
              The   standard   MIDI   file   format   is   a   very   strange   beast.   When   viewed   as   a  
    whole,   it   can   be   quite   overwhelming.   Of   course,   no   matter   how   you   look   at   it,  
  describing   a   piece   of   music   in   enough   detail   to   be   able   to   reproduce   it  
  accurately   is   no   small   task.   So,   while   complicated,   the   structure   of   the   midi  
  file   format   is   fairly   intuitive   when   understood.    
              I   must   insert   a   disclaimer   here   that   I   am   by   no   means   an   expert   with  
    midi   nor   midi   files.   I   recently   obtained   a   Gravis   UltraSound   board   for   my   PC,  
  and   upon   hearing   a   few   midi   files   (.MID)   thought,   "Gee,   I'd   like   to   be   able   to  
  make   my   own   .MID   files."   Well,   many   aggravating   hours   later,   I   discovered   that  
  this   was   no   trivial   task.   But,   I   couldn't   let   a   stupid   file   format   stop   me.  
  (besides,   I   once   told   my   wife   that   computers   aren't   really   that   hard   to   use,  
  and   I'd   hate   to   be   a   hypocrite)   So   if   any   errors   are   found   in   this  
  information,   please   let   me   know   and   I   will   fix   it.   Also,   this   document's   scope  
  does   not   extend   to   EVERY   type   of   midi   command   and   EVERY   possible   file  
  configuration.   It   is   a   basic   guide   that   should   enable   the   reader   (with   a  
  moderate   investment   in   time)   to   generate   a   quality   midi   file.  
   
  1.   Overview  
   
              A   midi   (.MID)   file   contains   basically   2   things,   Header   chunks   and   Track  
  chunks.   Section   2   explains   the   header   chunks,   and   Section   3   explains   the   track  
  chunks.   A   midi   file   contains   ONE   header   chunk   describing   the   file   format,  
  etc.,   and   any   number   of   track   chunks.   A   track   may   be   thought   of   in   the   same  
  way   as   a   track   on   a   multi-track   tape   deck.   You   may   assign   one   track   to   each  
  voice,   each   staff,   each   instrument   or   whatever   you   want.    
   
  2.   Header   Chunk  
   
              The   header   chunk   appears   at   the   beginning   of   the   file,   and   describes   the  
  file   in   three   ways.   The   header   chunk   always   looks   like:  
   
  4D   54   68   64   00   00   00   06   ff   ff   nn   nn   dd   dd  
   
  The   ascii   equivalent   of   the   first   4   bytes   is   MThd.   After   MThd   comes   the   4-byte  
  size   of   the   header.   This   will   always   be   00   00   00   06,   because   the   actual   header  
  information   will   always   be   6   bytes.    
   
  ff   ff   is   the   file   format.   There   are   3   formats:  
   
  0   -   single-track    
  1   -   multiple   tracks,   synchronous  
  2   -   multiple   tracks,   asynchronous  
   
  Single   track   is   fairly   self-explanatory   -   one   track   only.   Synchronous   multiple  
  tracks   means   that   the   tracks   will   all   be   vertically   synchronous,   or   in   other  
  words,   they   all   start   at   the   same   time,   and   so   can   represent   different   parts  
  in   one   song.   Asynchronous   multiple   tracks   do   not   necessarily   start   at   the   same  
  time,   and   can   be   completely   asynchronous.    
   
  nn   nn   is   the   number   of   tracks   in   the   midi   file.  
   
  dd   dd   is   the   number   of   delta-time   ticks   per   quarter   note.   (More   about   this  
  later)  
   
   
  3.   Track   Chunks  
   
  The   remainder   of   the   file   after   the   header   chunk   consists   of   track   chunks.  
  Each   track   has   one   header   and   may   contain   as   many   midi   commands   as   you   like.  
  The   header   for   a   track   is   very   similar   to   the   one   for   the   file:  
   
  4D   54   72   6B   xx   xx   xx   xx  
   
  As   with   the   header,   the   first   4   bytes   has   an   ascii   equivalent.   This   one   is  
  MTrk.   The   4   bytes   after   MTrk   give   the   length   of   the   track   (not   including   the  
  track   header)   in   bytes.    
              Following   the   header   are   midi   events.   These   events   are   identical   to   the  
  actual   data   sent   and   received   by   MIDI   ports   on   a   synth   with   one   addition.   A  
  midi   event   is   preceded   by   a   delta-time.   A   delta   time   is   the   number   of   ticks  
  after   which   the   midi   event   is   to   be   executed.   The   number   of   ticks   per   quarter  
  note   was   defined   previously   in   the   file   header   chunk.   This   delta-time   is   a  
  variable-length   encoded   value.   This   format,   while   confusing,   allows   large  
  numbers   to   use   as   many   bytes   as   they   need,   without   requiring   small   numbers   to  
  waste   bytes   by   filling   with   zeros.   The   number   is   converted   into   7-bit   bytes,  
  and   the   most-significant   bit   of   each   byte   is   1   except   for   the   last   byte   of   the  
  number,   which   has   a   msb   of   0.   This   allows   the   number   to   be   read   one   byte   at   a  
  time,   and   when   you   see   a   msb   of   0,   you   know   that   it   was   the   last   (least  
  significant)   byte   of   the   number.   According   to   the   MIDI   spec,   the   entire   delta-  
  time   should   be   at   most   4   bytes   long.    
              Following   the   delta-time   is   a   midi   event.   Each   midi   event   (except   a  
  running   midi   event)   has   a   command   byte   which   will   always   have   a   msb   of   1   (the  
  value   will   be   >=   128).   A   list   of   most   of   these   commands   is   in   appendix   A.   Each  
  command   has   different   parameters   and   lengths,   but   the   data   that   follows   the  
  command   will   have   a   msb   of   0   (less   than   128).   The   exception   to   this   is   a   meta-  
  event,   which   may   contain   data   with   a   msb   of   1.   However,   meta-events   require   a  
  length   parameter   which   alleviates   confusion.    
              One   subtlety   which   can   cause   confusion   is   running   mode.   This   is   where  
  the   actual   midi   command   is   omitted,   and   the   last   midi   command   issued   is  
  assumed.   This   means   that   the   midi   event   will   consist   of   a   delta-time   and   the  
  parameters   that   would   go   to   the   command   if   it   were   included.    
   
  4.   Conclusion  
   
              If   this   explanation   has   only   served   to   confuse   the   issue   more,   the  
  appendices   contain   examples   which   may   help   clarify   the   issue.   Also,   2  
  utilities   and   a   graphic   file   should   have   been   included   with   this   document:    
   
  DEC.EXE   -   This   utility   converts   a   binary   file   (like   .MID)   to   a   tab-delimited  
  text   file   containing   the   decimal   equivalents   of   each   byte.  
   
  REC.EXE   -   This   utility   converts   a   tab-delimited   text   file   of   decimal   values  
  into   a   binary   file   in   which   each   byte   corresponds   to   one   of   the   decimal  
  values.  
   
  MIDINOTE.PS   -   This   is   the   postscript   form   of   a   page   showing   note   numbers   with  
  a   keyboard   and   with   the   standard   grand   staff.  
                                                                                                                                                    Appendix   A  
   
  1.   MIDI   Event   Commands  
   
  Each   command   byte   has   2   parts.   The   left   nybble   (4   bits)   contains   the   actual  
  command,   and   the   right   nybble   contains   the   midi   channel   number   on   which   the  
  command   will   be   executed.   There   are   16   midi   channels,   and   8   midi   commands   (the  
  command   nybble   must   have   a   msb   of   1).  
  In   the   following   table,   x   indicates   the   midi   channel   number.   Note   that   all  
  data   bytes   will   be   <128   (msb   set   to   0).  
   
  Hex             Binary               Data                     Description  
  8x               1000xxxx           nn   vv                   Note   off   (key   is   released)  
                                                                          nn=note   number  
                                                                          vv=velocity  
   
  9x               1001xxxx           nn   vv                   Note   on   (key   is   pressed)  
                                                                          nn=note   number  
                                                                          vv=velocity  
   
  Ax               1010xxxx           nn   vv                   Key   after-touch  
                                                                          nn=note   number  
                                                                          vv=velocity  
   
  Bx               1011xxxx           cc   vv                   Control   Change  
                                                                          cc=controller   number  
                                                                          vv=new   value  
   
  Cx               1100xxxx           pp                         Program   (patch)   change  
                                                                          pp=new   program   number  
   
  Dx               1101xxxx           cc                         Channel   after-touch  
                                                                          cc=channel   number  
   
  Ex               1110xxxx           bb   tt                   Pitch   wheel   change   (2000H   is   normal   or   no  
                                                                          change)  
                                                                          bb=bottom   (least   sig)   7   bits   of   value  
                                                                          tt=top   (most   sig)   7   bits   of   value  
  The   following   table   lists   meta-events   which   have   no   midi   channel   number.   They  
  are   of   the   format:  
   
  FF   xx   nn   dd  
   
  All   meta-events   start   with   FF   followed   by   the   command   (xx),   the   length,   or  
  number   of   bytes   that   will   contain   data   (nn),   and   the   actual   data   (dd).  
   
  Hex             Binary               Data                     Description  
  00               00000000           nn   ssss               Sets   the   track's   sequence   number.  
                                                                          nn=02   (length   of   2-byte   sequence   number)  
                                                                          ssss=sequence   number  
   
  01               00000001           nn   tt   ..             Text   event-   any   text   you   want.  
                                                                          nn=length   in   bytes   of   text  
                                                                          tt=text   characters  
   
  02               00000010           nn   tt   ..             Same   as   text   event,   but   used   for  
                                                                          copyright   info.  
                                                                          nn   tt=same   as   text   event  
   
  03               00000011           nn   tt   ..             Sequence   or   Track   name  
                                                                          nn   tt=same   as   text   event  
   
  04               00000100           nn   tt   ..             Track   instrument   name  
                                                                          nn   tt=same   as   text   event  
   
  05               00000101           nn   tt   ..             Lyric  
                                                                          nn   tt=same   as   text   event  
   
  06               00000110           nn   tt   ..             Marker  
                                                                          nn   tt=same   as   text   event  
   
  07               00000111           nn   tt   ..             Cue   point  
                                                                          nn   tt=same   as   text   event  
   
  2F               00101111           00                         This   event   must   come   at   the   end   of   each  
                                                                          track  
   
  51               01010001           03   tttttt           Set   tempo  
                                                                          tttttt=microseconds/quarter   note  
   
  58               01011000           04   nn   dd   ccbb   Time   Signature  
                                                                          nn=numerator   of   time   sig.  
                                                                          dd=denominator   of   time   sig.   2=quarter  
                                                                          3=eighth,   etc.  
                                                                          cc=number   of   ticks   in   metronome   click  
                                                                          bb=number   of   32nd   notes   to   the   quarter  
                                                                          note  
   
  59               01011001           02   sf   mi             Key   signature  
                                                                          sf=sharps/flats   (-7=7   flats,   0=key   of   C,  
                                                                          7=7   sharps)  
                                                                          mi=major/minor   (0=major,   1=minor)  
   
  7F               01111111           xx   dd   ..             Sequencer   specific   information  
                                                                          xx=number   of   bytes   to   be   sent  
                                                                          dd=data  
  The   following   table   lists   system   messages   which   control   the   entire   system.  
  These   have   no   midi   channel   number.   (these   will   generally   only   apply   to  
  controlling   a   midi   keyboard,   etc.)  
   
  Hex             Binary               Data                     Description  
  F8               11111000                                       Timing   clock   used   when   synchronization   is  
                                                                          required.  
   
  FA               11111010                                       Start   current   sequence  
   
  FB               11111011                                       Continue   a   stopped   sequence   where   left  
                                                                          off  
   
  FC               11111100                                       Stop   a   sequence  
   
   
  The   following   table   lists   the   numbers   corresponding   to   notes   for   use   in   note    
  on   and   note   off   commands.  
   
   
  Octave||                                           Note   Numbers  
        #     ||  
              ||   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   |  
   
   
                                                                  BIBLIOGRAPHY  
   
      "MIDI   Systems   and   Control"   Francis   Rumsey     1990   Focal   Press  
   
      "MIDI   and   Sound   Book   for   the   Atari   ST"   Bernd   Enders   and   Wolfgang   Klemme  
                      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");  
  }  

WinMM.dll 函数汇总

auxGetDevCaps                  查询指定的辅助输出设备以确定其性能
auxGetNumDevs                  检取系统中存在的辅助输出设备的数量
auxGetVolume                   返回指定的辅助输出设备的当前卷设备
auxOutMessage                  向指定的辅助输出设备发送一条消息
auxSetVolume                   在指定的辅助输出设备中设置卷
CloseDirver                    关闭指定的可安装驱动器
DefDriverProc                  为任何不由可安装驱动器处理的消息提供的缺省处理
Drivercallback                 调用一个回调函数,发送一条消息给窗口或将一个线程的阻塞解除
DrvGetModuleHandle             返回包含指定可安装驱动器模块的实例句柄
DrvsendMessage                 把指定的消息发送给可安装驱动器
GetDriverModuleHandle          返回包含指定可安装驱动器模块的实例句柄
joyGetDevCaps                  查询指定的游戏杆设备以确定其性能
joyGetNumDevs                  返回系统支持的游戏杆设备的数量
joyGetPos                      查询指定的游戏杆设备的位置和活动性
joyGetPosEx                    查询一个游戏杆设备的位置和它的按扭状态
joyGetThreshold                查询指定的游戏杆设备的当前移动阈值
joyReleaseCapture              释放由JoySetCapture函数设置的在指定游戏杆设备上的捕获
joySetCapture                  发送一个游戏杆消息到指定的窗口
joySetThreshold                设置指定的游戏杆设备的移动阈值
mciGetCreatorTask              为指定的MCI设备检取其创建的任务
mciGetDeviceID                 返回和打开设备名相匹配的设备标识符
mciGetErrorString              检取描述指定媒介控制接口错误代码的字符串
mciGetYieldProc                返回和媒介控制接口的WAIT标志相关的回调函数的地址
mciSendCommand                 向指定的媒介控制接口设备发送一条命令
mciSendString                  向指定的媒介控制接口设备发送一个字符串
mciSetYieldProc                设置一个过程地址,在MCI设备因指定了WAIT标志而等待一个命令完成时,该过程被周期性调用
midiConnect                    将指定的MIDI输入设备连接到输出设备
midiDisconnect                 断开MIDI输入设备和输出设备的连接
midiInAddBuffer                向指定的音乐仪器数字接口的输入设备增加一个缓冲区
midiInClose                    关闭指定的音乐仪器数字接口的输入设备
midiInGetDveCaps               查询指定的音乐仪器数字接口的输入设备,以确定其性能
midiInGetErrorText             检取有关音乐仪器数字接口的输入设备指定错误的文本说明
midiInGetID                    获得一个音乐一起数字接口的输入设备的标识符
midiInGetNumDevs               检取系统中音乐仪器数字接口的输入设备的数量
midiInMessage                  向指定的音乐仪器数字接口的输入设备驱动器发送一条消息
midiInOpen                     打开指定的音乐仪器数字接口的输入设备
midiInPrepareHeader            为音乐仪器数字接口的输入设备准备一个缓冲区
midiInReset                    在给定的MIDI输入设备上输入,并将所有挂起的输入缓冲区标记为已执行的
midiInStart                    启动在指定的音乐仪器数字接口的输入设备上的输入
midiInStop                     停止在给定的音乐仪器数字接口的输入设备上的输入
midiInUnprepareHeader          消除由midiInPrepareHeader函数完成的准备
midiOutCacheDrumPatches        请求内部的一个MIDI合成设备预装指定的基于键的击打音色集
midiOutCachePatches            请求内部的音乐仪器数字接口的合成设备预装指定的音色集
midiOutClose                   关闭指定的音乐仪器数字接口的输出设备
midiOutGetDevCaps              查询指定的音乐仪器数字接口的输出设备,以确定其性能
midiOutGetErrorText            检取有关MIDI输出设备指定采取的文本说明
midiOutGetID                   检取指定的MIDI输出设备的标识符
midiOutGetNumDevs              检取系统中存在的MIDI输出设备的数量
midiOutGetVolume               返回一个MIDI输出设备的当前卷设置
midiOutLongMsg                 向指定的MIDI输出设备发送一条系统专用的MIDI消息
midiOutMessage                 向一MIDI输出设备驱动器发送一条消息
midiOutOpen                    打开指定的MIDI输出设备进行回放
midiOutPrepareHeader           为MIDI输出设备准备一个缓冲区
midiOutReset                   为指定的MIDI输出设备关闭所有MIDI通道上的所有标志
midiOutSetVolume               设置一个MIDI输出设备的卷
midiOutShortMsg                向指定的MIDI输出设备发送一条短MIDI消息
midiOutUnprepareHeader         清除由midiOutPrepareHeader函数完成的准备
midiStreamClose                关闭一个打开的MIDI流
midiStreamOpen                 为输出,打开一个MIDI流
midiStreamOut                  在MIDI输出设备上播放或排队一个MIDI数据流
midiStreamPause                暂停一个MIDI流的播放
midiStreamPosition             在一个MIDI流中检取当前位置
midiStreamProperty             设置或检取与MIDI输出设备相关MIDI数据流的特性
midiStreamRestart              重新启动一个暂停的MIDI流
midiStreamStop                 关掉指定MIDI输出设备的所有MIDI通道
mixerClose                     关闭指定的混频器
mixerGetControlDetails         检取和一个声频指线路相关的单一控件的细节
mixerGetDevCaps                查询指定的混频器以确定其性能
mixerGetID                     获取指定混频器的标识符
mixerGetLineContrils           检取和一个声频线路相关的一个或多个控件
mixerGetLineInfo               检取混频器有关特有线路的信息
mixerGetNumDevs                返回系统中存在的混频器的数量
mixerMessage                   把一个定制混频器驱动器消息直接发送给混频器驱动器
mixerOpen                      打开指定的混频器,在应用程序关闭该句柄前保证该设备不被移走
mixerSetControlDetails         设置和一个声频指线路相关的单一控件的细节
mmioAsvance                    填充一个文件的IO缓冲区
mmioAscend                     取出一个RIFF文件块
mmioClose                      关闭有mmioOpen打开的文件
mmioCreateChunk                创建由mmioOpen函数打开的RIFF文件中的一个块
mmioDescend                    进入由mmioOpen函数打开的RIFF文件的块中,并查找一个块
mmioFlush                      把文件缓冲区的数据写入磁盘中
mmioGetInfo                    检取有关由mmioOpen函数创建的RIFF文件的信息
mmioInstallIOProcA             装入或删除一个自定义的IO过程
mmioOpen                       为输入输出打开一个文件
mmioRead                       从由mmioOpen函数打开的文件中读取指定字节数的数据
mmioRename                     重新命名指定的文件
mmioSeek                       改变由mmioOpen函数打开的文件中的当前指针位置
mmioSendMessage                向与指定文件相联系的IO过程发送一条消息
mmioSetBuffer                  允许或禁止文件缓冲区的IO,或改变这个缓冲区,或改变这个缓冲区的大小
mmioSetInfo                    更新从被打开文件中检取的信息
mmioStringToFOURCC             把一个以NULL结束的字符串转换成一个4字符代码
mmioWrite                      向由mmioOpen函数打开的文件中写入指定字节数的数据
mmsystemGetVersion             返回多媒体扩展系统软件的当前版本号
OpenDriver                     打开一个可安装驱动器实例,并用缺省设置或指定值初始化该实例
PlaySound                      播放一个波形声音
SendDriveMessage               向指定的可安装驱动器发送一条消息
SndPlaySound                   播放一个由文件名或由登记的[sound]段的入口指定的波形声音
timeBeginPeriod                设置应用程序或驱动程序使用的最小定时器分辨率
timeEndPeriod                  清除应用程序或驱动程序使用的最小定时器分辨率
timeGetDevCaps                 查询定时器设备以确定其性能
timeGetSystemTime              检取从WINDOWS开始已逝去的毫秒数
timeGetTime                    检取从WINDOWS开始已逝去的毫秒数,此函数比上一条函数开销小
timeKillEvent                  毁掉指定的定时器回调事件
timeSetEvent                   设置一个定时器回调事件
waveInAddBuffer                向波形输入设备添加一个输入缓冲区
WaveInClose                    关闭指定的波形输入设置
waveInGetDevCaps               查询指定的波形输入设备以确定其性能
waveInGetErrorText             检取由指定的错误代码标识的文本说明
waveInGetID                    获取指定的波形输入设备的标识符
waveInGetNumDevs               返回系统中存在的波形输入设备的数量
waveInGetPosition              检取指定波形输入设备的当前位置
waveInMessage                  发送一条消息给波形输入设备的驱动器
waveInOpen                     为录音而打开一个波形输入设备
waveInPrepareHeader            为波形输入准备一个输入缓冲区
waveInReset                    停止给定的波形输入设备的输入,且将当前位置清零
waveInStart                    启动在指定的波形输入设备的输入
waveInStop                     停止在指定的波形输入设备上的输入
waveInUnprepareHeader          清除由waveInPrepareHeader函数实现的准备
waveOutBreakLoop               中断给定的波形输出设备上一个循环,并允许播放驱动器列表中的下一个块
waveOutClose                   关闭指定的波形输出设备
waveOutGetDevCaps              查询一个指定的波形输出设备以确定其性能
waveOutGetErrorText            检取由指定的错误代码标识的文本说明
waveOutGetID                   检取指定的波形输出设备的标识符
waveOutGetNumDevs              检取系统中存在的波形输出设备的数量
waveOutGetPitch                查询一个波形输出设备的当前音调设置
waveOutGetPlaybackRate         查询一个波形输出设备当前播放的速度
waveOutGetPosition             检取指定波形输出设备的当前播放位置
waveOutGetVolume               查询指定波形输出设备的当前音量设置
waveOutMessage                 发送一条消息给一个波形输出设备的驱动器
waveOutOpen                    为播放打开一个波形输出设备
waveOutPause                   暂停指定波形输出设备上的播放
waveOutPrepareHeader           为播放准备一个波形缓冲区
waveOutRestart                 重新启动一个被暂停的波形输出设备
waveOutSetPitch                设置一个波形输出设备的音调
waveOutSetPlaybackRate         设置指定波形输出设备的速度
waveOutSetVolume               设置指定的波形输出设备的音量
waveOutUnprepareHeader         清除由waveOutPrepareHeader函数实现的准备
waveOutWrite                   向指定的波形输出设备发送一个数据块