小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

標(biāo)準(zhǔn)MIDI文件格式_ - 文件格式 - 文件格式_開發(fā)文檔

 昵稱538 2005-09-29

標(biāo)準(zhǔn)MIDI文件格式
達(dá)思挺·考德威爾

標(biāo)準(zhǔn)的MIDI文件格式就像奇異的獸??傮w看來(lái),它是那樣的讓你無(wú)法抗拒。當(dāng)然,你怎樣看它無(wú)關(guān)緊要,可是用足夠多的描述符描述一段音樂并使它能夠重現(xiàn),可不是很少的工作就可以完成的。然而,它雖然復(fù)雜,但是真正理解之后,MIDI文件格式的結(jié)構(gòu)還是很直觀明了的。

在這里我必須放棄一些東西,因?yàn)楫吘刮也皇荕IDI也不是MIDI文件專家!最近我為我的PC準(zhǔn)備了一塊Gravis 超音頻音效卡,利用它聽完幾段MIDI文件(.mid)之后,想:“呵,我要是能夠制作自己的MIDI(.mid)文件該多好啊!”嗯,經(jīng)過(guò)煩人的幾個(gè)小時(shí)之后,我發(fā)現(xiàn),那些并不是沒有價(jià)值的工作。但是,我是不會(huì)讓一個(gè)冗長(zhǎng)的文件格式就能夠阻止的(此外,我告訴過(guò)我的妻子,計(jì)算機(jī)不是很難用的,而且我十分憎恨當(dāng)一個(gè)偽君子)。那么,在這篇文章中如果發(fā)現(xiàn)什么錯(cuò)誤,請(qǐng)讓我知道,我會(huì)修改它的。同時(shí),這份文檔的范圍并沒有提供所有類型的MIDI命令和任何可能的文件配置!這篇基本指南將使讀者能夠(以中等的時(shí)間投資)制作出MIDI類型的文件。

1.概述:

一個(gè)MIDI文件基本上由兩個(gè)部分組成,頭塊和軌道塊。第二節(jié)講述頭塊,第三節(jié)講述軌道塊。一個(gè)MIDI文件有一個(gè)頭塊用來(lái)描述文件的格式、許多的軌道塊等內(nèi)容。一個(gè)軌道可以想象為像一個(gè)大型多音軌錄音機(jī)那樣,你可以為某種聲音、某種樂譜、某種樂器或者你需要的任何東西分配一個(gè)軌道。

2.頭塊:

頭塊出現(xiàn)在文件的開頭,有三種方式來(lái)描述文件。頭塊看起來(lái)一直是這樣的:
4D 54 68 64 00 00 00 06 ff ff nn nn dd dd

前4個(gè)字節(jié)等同于ASCII碼MThd,接著MThd之后的4個(gè)字節(jié)是頭的大小。它將一直是00 00 00 00 06,因?yàn)楝F(xiàn)行的頭信息將一直是6字節(jié)。

ff ff是文件的格式,有3種格式:
0-單軌
1-多規(guī),同步
2-多規(guī),異步

單軌,很顯然就只有一個(gè)軌道。同步多軌意味著所有軌道都是垂直同步的,或者其他的措辭為他們都在同一時(shí)間開始,并且可以表現(xiàn)一首歌的不同部分。異步多軌沒有必要同時(shí)開始,而且可以完全的不同步。

nn nn 是MIDI文件中的軌道數(shù)。
dd dd 是每個(gè)4分音符delta-time節(jié)奏數(shù)(這之后將做詳細(xì)介紹)。

3.軌道塊:

頭塊之后剩下的文件部分是軌道塊。每一個(gè)軌道包含一個(gè)頭,并且可以包含你所希望的許多MIDI命令。軌道頭與文件頭及其相似:

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

與頭一致,前4個(gè)字節(jié)是ASCII嗎,這個(gè)是MTrk,緊跟MTrk的4個(gè)字節(jié)給出了以字節(jié)為單位的軌道的長(zhǎng)度(不包括軌道頭)。

在頭之下是MIDI事件,這些事件同現(xiàn)行的可以被帶有累加的MIDI合成器端口接受和發(fā)送的數(shù)據(jù)是相同的。一個(gè)MIDI 事件先于一個(gè)delta-time。一個(gè)delta-time是一個(gè)MIDI事件被執(zhí)行后的節(jié)奏數(shù),每個(gè)四分之一音符的節(jié)奏數(shù)先前已經(jīng)定義在了文件的頭塊中。這個(gè)delta-time是一個(gè)可變長(zhǎng)度的編碼值。這種格式雖然混亂,可是允許根據(jù)需要利用多位表示較大的數(shù)值,這不會(huì)因?yàn)樾枨笮〉臄?shù)值情況下以添零的方式浪費(fèi)掉一些字節(jié)!數(shù)值被轉(zhuǎn)換為7位的字節(jié),并且除了最后一個(gè)字節(jié)以最高有效位是0外,各個(gè)字節(jié)最有意義的一位是1,。這就允許一個(gè)數(shù)值被一次一個(gè)字節(jié)地讀取,你如果發(fā)現(xiàn)最高有效位是0,則這就是這個(gè)數(shù)值的最后一位(意義比較小)。依照MIDI說(shuō)明,全部delta-time的長(zhǎng)度最多超過(guò)4字節(jié)。

delta-time 之后就是MIDI事件,每個(gè)MIDI事件(除了正在運(yùn)行的事件外)帶有一個(gè)最高有效位總是1的命令字節(jié)(值將>128)。大部分命令的列表在附錄A中。每個(gè)命令都有不同的參數(shù)和長(zhǎng)度,但是接下來(lái)的數(shù)據(jù)將是最高有效位為零(值將<128)。這里有個(gè)例外就是meta-event,最高有效位可以是1。然而,meta-events需要一個(gè)長(zhǎng)的參數(shù)以區(qū)分。

微小失誤就可以導(dǎo)致混亂的是運(yùn)行模式,這是現(xiàn)行MIDI命令所忽略的地方,并且最終發(fā)行的MIDI命令是假定的。這就意味這如果包含了命令,那么MIDI事件就是由delta-time與參數(shù)組成而轉(zhuǎn)換的。

4.綜述:

如果這份說(shuō)明僅僅是使問題更加混亂,那么以下提供的例子可能有助于澄清問題!同時(shí),兩個(gè)公用程序和一個(gè)圖解文件包含在這個(gè)文檔里面:

DEC.EXE——這個(gè)公共程序是將二進(jìn)制文件(比如.MID)轉(zhuǎn)換成以十進(jìn)制表示的對(duì)應(yīng)每個(gè)字節(jié)的有標(biāo)記界限的文本文件。

REC.EXE——這個(gè)公共程序是將有標(biāo)記界限的十進(jìn)制數(shù)文本文件對(duì)應(yīng)的每一字節(jié)轉(zhuǎn)換成二進(jìn)制文件。

MIDINOTE.PS——這是一個(gè)對(duì)應(yīng)鍵盤和五線譜的音符數(shù)字附錄頁(yè)。


附錄A

1.MIDI事件命令

每個(gè)命令字節(jié)有兩部分,左nybble(4位)包含現(xiàn)行的命令,右nybble包含將被執(zhí)行的命令的通道號(hào),這里有16各MIDI通道8個(gè)MIDI命令(命令nybble必須最高有效位是1的)。在下表中,X表示MIDI通道號(hào)。所有的音符即數(shù)據(jù)字節(jié)都<128(最高有效位是0)。

十六進(jìn)制 二進(jìn)制 數(shù)據(jù) 描述

8x      1000xxxx    nn vv        音符關(guān)閉 (釋放鍵盤)
                            nn=音符號(hào)
                            vv=速度

9x      1001xxxx    nn vv        音符打開 (按下鍵盤)
                            nn=音符號(hào)
                            vv=速度

Ax      1010xxxx    nn vv        觸摸鍵盤以后
                            nn=音符號(hào)
                            vv=速度

Bx      1011xxxx    cc vv        調(diào)換控制
                            cc=控制號(hào)
                            vv=新值

Cx      1100xxxx    pp            改變程序(片斷)
                            pp=新的程序號(hào)

Dx      1101xxxx    cc            在通道后接觸
cc=管道號(hào)

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

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

FF xx nn dd

所有的 meta-events 是以 FF 開頭的命令 (xx),長(zhǎng)度,或者含在數(shù)據(jù)的字節(jié)數(shù)(nn),現(xiàn)行的數(shù)據(jù)(dd)

十六進(jìn)制 二進(jìn)制 數(shù)據(jù) 描述
00      00000000    nn ssss      設(shè)定軌道的序號(hào)
                            nn=02 (兩字節(jié)長(zhǎng)度的序號(hào))
                            ssss=序號(hào)

01      00000001    nn tt ..      你需要的所有文本事件
                        nn=以字節(jié)為單位的文本長(zhǎng)度
                            tt=文本字符

02      00000010    nn tt ..      同文本的事件, 但是用于版權(quán)信息
                           nn tt=同文本事件

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

04      00000100    nn tt ..      軌道樂器名
                            nn tt=同文本事件

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

06      00000110    nn tt ..      標(biāo)簽
                            nn tt=同文本事件

07      00000111    nn tt ..      浮點(diǎn)音符
                           nn tt=同文本事件

2F      00101111    00            這個(gè)事件一定在每個(gè)軌道的結(jié)尾出現(xiàn)

51      01010001    03 tttttt    設(shè)定拍子
                                tttttt=微秒/四分音符

58      01011000    04 nn dd cc bb 拍子記號(hào)
                                nn=拍子記號(hào)分子
                                dd=拍子記號(hào)分母2=四分之一
                                3=8分拍, 等等.
                                cc=節(jié)拍器的節(jié)奏
                                bb=對(duì)四分之一音符標(biāo)注的第32號(hào)數(shù)字

59    01011001    02 sf mi      音調(diào)符號(hào)
                              sf=升調(diào)/降調(diào)(-7=7 降調(diào), 0=基準(zhǔn)C調(diào),7=7 升調(diào))
                              mi=大調(diào)/小調(diào)(0=大調(diào), 1=小調(diào))

7F      01111111    xx dd ..      音序器的詳細(xì)信息
                            xx=被發(fā)送的字節(jié)數(shù)
                            dd=數(shù)據(jù)

下表列出了控制整個(gè)系統(tǒng)的系統(tǒng)消息。這里沒有MIDI通道數(shù) (這些一般僅應(yīng)用于MIDI鍵盤等.)

十六進(jìn)制      二進(jìn)制  數(shù)據(jù)          描述

F8      11111000                  同步所必須的計(jì)時(shí)器
FA      11111010                  開始當(dāng)前的隊(duì)列
FB      11111011                  從停止的地方繼續(xù)一個(gè)隊(duì)列
FC      11111100                  停止一個(gè)隊(duì)列

下表列出的是與音符相對(duì)應(yīng)的命令標(biāo)記。
八度音階¦¦                    音符號(hào)
  #  ¦¦
      ¦¦ 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");
}


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多