程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2ME >> MID格局詳解

MID格局詳解

編輯:J2ME

我想寫一個工具,把mid格局的音樂在sega genesis上播放,mid文件的格局如下:

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      1000***x    nn vv        音符封閉 (開釋鍵盤)
                            nn=音符號
                            vv=速度

9x      1001***x    nn vv        音符打開 (按下鍵盤)
                            nn=音符號
                            vv=速度

Ax      1010***x    nn vv        觸摸鍵盤以後
                            nn=音符號
                            vv=速度

Bx      1011***x    cc vv        調換把持
                            cc=把持號
                            vv=新值

Cx      1100***x    pp            轉變程序(片段)
                            pp=新的程序號

Dx      1101***x    cc            在通道後接觸
        cc=管道號

Ex      1110***x    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
[email protected] with the phrase GET MIDISPEC PACKAGE in the message.
------------------------------ DEC.CPP ------------------------------------

/*  file  dec.cpp

by  Dustin Caldwell    ([email protected])

*/


#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  ([email protected])\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  ([email protected])
*/

#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  ([email protected])\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");
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved