«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告

本站技术贴除标明为“原创”的之外,其余均为网上转载,文中我会尽量保留原作者姓名,若有侵权请与我联系,我将第一时间做出修改。谢谢!

             ——既瑜


天气预报(南京)


我的分类(专题)

首页(183)
【趣味文摘】(22)
【五子连珠】(13)
【技术文档】(136)
【电脑技术】(6)
【疑难问题】(1)
【我的心情】(5)


最新日志
花语(中英文对照版)
各种花的花语
NTFS格式的7个精彩问答(pconli
童言无忌,有趣得一蹋
给MM修电脑的三个步骤[转载]
J2EE 面试题综合
JAVA编程规则
[转] P2P之UDP穿透NAT的原理与
[转]词法分析器
文件加密技术
一个让人发狂的PI求解C程序
[转]直线生成算法之DDA
[转]利用内核对象----互斥量实现应用
[转]如何正确的计算文件收发进度
双机调试VC程序
[转]分治法优化大整数乘法 C++实现
浮点数值的内存结构
[转]双链表实现大整数的加法与乘法[VC
拜占廷将军问题[转]
某人的挂QQ的程序源代码,虽然没用了,拿

最新回复
回复:vc中的CString的操作
回复:[转]分治法优化大整数乘法 C++
回复:[转]分治法优化大整数乘法 C++
回复:花语(中英文对照版)
回复:基本排序算法比较与选择[转载]
回复:c++中强制类型转换操作符小结
回复:c++中强制类型转换操作符小结
何必那么执着于是大头猫还是愤怒的小鸟,淡
回复:浮点数值的内存结构
回复:花语(中英文对照版)
回复:花语(中英文对照版)
回复:花语(中英文对照版)
回复:花语(中英文对照版)
回复:花语(中英文对照版)
回复:32位位图到24位位图的转换
dren, ages 16 and 20
回复:花语(中英文对照版)
回复:花语(中英文对照版)
回复:花语(中英文对照版)
回复:各种花的花语

留言板
签写新留言

不是0-1背包喔
桂花的花语``
谢谢
提议
提议

统计
blog名称:★既瑜★
日志总数:183
评论数量:636
留言数量:-25
访问次数:1406881
建立时间:2005年3月12日

链接


http://www.nju.edu.cn
http://bbs.nju.edu.cn 
http://www.t7-online.com
http://www.csdn.net
http://www.91f.net
http://www.crsky.com
我的MSN BLOG 

联系我

  OICQ:215768265
  njucs2001@hotmail.com
  erichoo1982@gmail.com

 

W3CHINA Blog首页    管理页面    写新日志    退出


[【技术文档】]标准MIDI文件格式
既瑜(224499) 发表于 2005/7/13 9:07:01

标准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.------------------------------ 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");}

阅读全文(2836) | 回复(0) | 编辑 | 精华


发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)

站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.625 second(s), page refreshed 144768467 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号