The MThd header has an ID of MThd, and a Length of 6.
Let's examine the 6 data bytes (which follow the MThd header) in an MThd chunk.
The first two data bytes tell the Format (which I prefer to call "type"). There are actually 3 different types (ie, formats) of MIDI files. A type of 0 means that the file contains one single track containing midi data on possibly all 16 midi channels. If your sequencer sorts/stores all of its midi data in one single block of memory with the data in the order that it's "played", then it should read/write this type. A type of 1 means that the file contains one or more simultaneous (ie, all start from an assumed time of 0) tracks, perhaps each on a single midi channel. Together, all of these tracks are considered one sequence or pattern. If your sequencer separates its midi data (i.e. tracks) into different blocks of memory but plays them back simultaneously (ie, as one "pattern"), it will read/write this type. A type of 2 means that the file contains one or more sequentially independant single-track patterns. If your sequencer separates its midi data into different blocks of memory, but plays only one block at a time (ie, each block is considered a different "excerpt" or "song"), then it will read/write this type.
The next 2 bytes tell how many tracks are stored in the file, NumTracks. Of course, for format type 0, this is always 1. For the other 2 types, there can be numerous tracks.
The last two bytes indicate how many Pulses (i.e. clocks) Per Quarter Note (abbreviated as PPQN) resolution the time-stamps are based upon, Division. For example, if your sequencer has 96 ppqn, this field would be (in hex):
00 60
NOTE: The 2 bytes that make up the Division are stored in (Motorola) "Big Endian" byte order, not (Intel) "Little Endian" reverse byte order. The same is true for the NumTracks and Format.
Alternately, if the first byte of Division is negative, then this represents the division of a second that the time-stamps are based upon. The first byte will be -24, -25, -29, or -30, corresponding to the 4 SMPTE standards representing frames per second. The second byte (a positive number) is the resolution within a frame (ie, subframe). Typical values may be 4 (MIDI Time Code), 8, 10, 80 (SMPTE bit resolution), or 100.
You can specify millisecond-based timing by the data bytes of -25 and 40 subframes.
Here's what an MThd chunk looks like if you defined it in C:
struct MTHD_CHUNK{ /* Here's the 8 byte header that all chunks must have */char ID[4]; /* This will be 'M','T','h','d' */unsigned long Length; /* This will be 6 *//* Here are the 6 bytes */unsigned short Format; unsigned short NumTracks; unsigned short Division;};
And here's an example of a complete MThd chunk (with header) if you examined it in a hex editor:
4D 54 68 64 MThd ID
00 00 00 06 Length of the MThd chunk is always 6.
00 01 The Format type is 1.
00 02 There are 2 MTrk chunks in this file.
E7 28 Each increment of delta-time represents a millisecond.
A standard MIDI file is composed of "chunks". It starts with a header chunk and is followed by one or more track chunks. The header chunk contains data that pertains to the overall file. Each track chunk defines a logical track.
A chunk always has three components, similar to Microsoft RIFF files (the only difference is that SMF files are big-endian, while RIFF files are usually little-endian). The three parts to each chunk are:
The track ID string which is four charcters long. For example, header chunk IDs are "MThd", and Track chunk IDs are "MTrk".
next is a four-byte unsigned value that specifies the number of bytes in the data section of the track (part 3).
finally comes the data section of the chunk. The size of the data is specified in the length field which follows the chunk ID (part 2).
The header chunk consists of a literal string denoting the header, a length indicator, the format of the MIDI file, the number of tracks in the file, and a timing value specifying delta time units. Numbers larger than one byte are placed most significant byte first.
the literal string MThd, or in hexadecimal notation: 0x4d546864. These four characters at the start of the MIDI file indicate that this is a MIDI file.
<header_length> 4 bytes
length of the header chunk (always 6 bytes long--the size of the next three fields which are considered the header chunk).
<format> 2 bytes
0 = single track file format 1 = multiple track file format 2 = multiple song file format (i.e., a series of type 0 files)
<n> 2 bytes
number of track chunks that follow the header chunk
<division> 2 bytes
unit of time for delta timing. If the value is positive, then it represents the units per beat. For example, +96 would mean 96 ticks per beat. If the value is negative, delta times are in SMPTE compatible units.
Several different values in SMF events are expressed as variable length quantities (e.g. delta time values). A variable length value uses a minimum number of bytes to hold the value, and in most circumstances this leads to some degree of data compresssion.
A variable length value uses the low order 7 bits of a byte to represent the value or part of the value. The high order bit is an "escape" or "continuation" bit. All but the last byte of a variable length value have the high order bit set. The last byte has the high order bit cleared. The bytes always appear most significant byte first.
Here are some examples:
Variable length Real value
0x7F 127 (0x7F)
0x81 0x7F 255 (0xFF)
0x82 0x80 0x00 32768 (0x8000)
However, MIDI data by itself is not useful to store unless you also store/record a time associated with that MIDI data.
Therefore, Standard MIDI Files contain at the top level things called events. Each event consists of two components: a time, and a MIDI message. These time/message pairs follow each other one after another in a MIDI file, so the order of data in a MIDI file goes like this in one long stream:
time message time message time message time message time message
time message time message time message time message time message
time message time message time message time message time message
time message time message time message time message time message
The time value is a measurement of the time to wait before playing the next message in the stream of MIDI file data. This method of specifying the time is called delta time, where delta is a jargon term in mathematics and related fields which means "difference" -- so a delta time is a time value which specifies the duration (or time difference) between two events.
Now note that MIDI messages usually come after each other quickly -- especially if there are chords. So the predominant time between each MIDI message in a MIDI file is going to be small.
MIDI files, like plain MIDI data, are stored in the form of bytes. Bytes can be though of as numbers in the range from 0 to 255, since a byte is a binary number with 8 digits, which can store numbers from 00000000 to 11111111.
This poses a problem in binary data such as MIDI files. The MIDI file is just a stream of numbers, each of which is in the range from 0 to 255. How do you tell when a time or message starts/stops? For example, here is some data from a MIDI file (in hexadecimal notation):
How do you separate this stream of data into time/message pairs? If you don't know anything about MIDI, you are in the same position as a computer who is reading this data. In order to to the segretation into time/data pairs you have to know the MIDI Protcol and about Variable Length Values. Once you have a basic understanding of MIDI files, you should be able to distinguish the time/message pairs with hardly any effort:
Notice that time values sometime are two bytes in length, and sometimes they are one byte in length. Using more than one byte for the delta time implies a longer time value. Time values in a MIDI file are stored as Variable Length Values (VLV). A VLV is a number with a variable width
I won't explain how to segment the MIDI message data here, but here is a simple algorithm for parsing a VLV value out of a byte stream:
If byte is greater or equal to 80h (128 decimal) then the next byte
is also part of the VLV,
else byte is the last byte in a VLV.
Why use VLV's? Why not use time values which are stored in fixed number of bytes which can store the maximum delta-time necessary? This is possible, and perhaps preferrable since this would make things easier. Then the byte stream in a MIDI file might look like this:
The people who designed the structure of the Standard MIDI file were concerned about storage space. The MIDI protocol was created in the early 1980's when PC computers often didn't have hard disks, and the floopy disks contains 256KB of information max. Now in the year 1999, a 1GB hard disk is considered small (which could hold around 5,000 256KB floppies on it). We can't easily change the MIDI file format now however, because there are lots of MIDI files and programs that read MIDI files which would become obsolete for no significant improvement in the file format other than to make it easier for humans to read (which they shouldn't be doing anyway).
Since delta times are usually small, we can use just one byte usually to store the time. However if delta times are large, then more than one byte is needed to store the delta time. Therefore, by using VLV's, the size of a MIDI file is reduced. So, you can think of VLV's as a form of compression.
Definition of Variable Length Values
A MIDI file Variable Length Value is stored in bytes. Each byte has two parts: 7 bits of data and 1 continuation bit. The highest-order bit is set to 1 if there is another byte of the number to follow. The highest-order bit is set to 0 if this byte is the last byte in the VLV.
To recreate a number represented by a VLV, first you remove the continuation bit and then concatenate the leftover bits into a single number.
To generate a VLV from a given number, break the number up into 7 bit units and then apply the correct continuation bit to each byte.
In theory, you could have a very long VLV number which was quite large; however, in the standard MIDI file specification, the maximum length of a VLV value is 5 bytes, and the number it represents can not be larger than 4 bytes.
Examples
The MIDI file delta-time 0h can be represented as a byte like this:
00000000
This is a variable length value with a length of one byte.
First segretate the continuation bit from the data bits for the value:
0 0000000
What is the continuation bit? It is zero. This means that there are no more bytes to follow this byte for the delta time's value. Now look and figure out what number they are. 0000000 in binary notation is equal to 0 hex, or 0 decimal.
Therefore the VLV 00000000 is equal to 0.
Now look at a harder example: 81 00 (hex).
Since 81 is larger than 80, you can see that the 00 byte is also part of the VLV. Lets look at 81 00 in binary notation:
10000001 00000000
Separate the continuation bit from the data bits:
1 0000001 0 0000000
Now you can see in binary notation what you can also see in hex notation -- that the first byte expects at least one more byte to follow it in the VLV. Remove the continuation bits:
0000001 0000000
This is the actual number that is represented by the VLV value 81 00, but maybe we should convert to decimal or hex so you understand it better. First, combine all of the bits into one clump:
00000010000000
I will convert first to hexadecimal, and later to decimal. For hexadecimal conversion of a binary number, arrange the digits into groups of 4, starting with the least siginificant (smallest, right) side of the number:
00 0000 1000 0000
There are two zeros left on the left size, so add two more zeros to make a grouping of four digits:
0000 0000 1000 0000
We can do this in decimal notation to show why this can be done: the number 0045 and 45 are the same number. Now, convert the binary groupings into hexadecimal digits:
0000 0000 1000 0000
0 0 8 0
Therefore the number is 0080 or 80 in hex notation. Convert 80 to decimal notation:
What are the units of measurements for delta times? In a MIDI file, the units are arbitrary, and you have to look at the header of the MIDI file to see what the units mean. For this example, the time units are 128 ticks to the quarter note, so 128 is a quarter note duration, 256 is a half-note, and 64 is an eighth-note duration.
For the class, you can use the program vlv to convert between variable length values and the numbers that they represent (or vice-versa).
Here are some more equivalences between VLV's and the number they represent:
Variable length (in hex) Real value in hex (dec)
7F 7F (127)
81 7F FF (255)
82 80 00 8000 (32768)
(一)、MIDI簡介
MIDI是Musical Instrument Digital Interface的縮寫, 直接翻譯就是"樂器數位介面," 它讓具有MIDI的裝置能夠以共同的方式 (語言) 來溝通. 在1983年的時候, 多家樂器製造廠商共同制定出MIDI 1.0的規格, 目的就是要讓不同的合成器(synthesizer) 可以互相溝通. 後來為了擴充MIDI的功能, 還增加了MIDI Time Code, Sample Dump Standard...等標準. 這個MIDI 1.0規格就一直使用到現在, 而沒有很大的改變.
MIDI訊號是以串列 (serial) 的方式傳送, 速率為每秒31,250 bits; 又每個MIDI message (一組MIDI資料的單位) 需要10 bits來記錄, 所以MIDI每秒鐘可以傳送3,125個資料. 請注意MIDI傳送的是數位控制訊號, 並不是聲音訊號 (audio signal). MIDI檔(延伸檔名為 .MID )與數位音效檔比較起來是非常小的.但是,在大部份時候必須去編輯並作最佳化處理. 欲編輯 MIDI 檔時, 必須使用 MIDI 編輯器(一般稱為 MIDI 序列器)序列器負責編排 MIDI 訊息並送至其他音源的電腦程式或電子裝置. 您也可以用來編輯已錄成的 MIDI 訊息
(二)、MIDI channel
每個MIDI裝置的MIDI channel共有16個, 在這16個channel中可以執行獨立的工作, 而接收訊息的模式有4種, 分別是
Mode 1: Omni-On Poly
Mode 2: Omni-On Mono
Mode 3: Omni-Off Poly
Mode 4: Omni-Off Mono
Mode 3是目前最常用的模式, Omni-Off指的是MIDI裝置會在MIDI訊息指定的channel作反應; 而Poly是能夠同時發出超過一個的聲音, 直到超出MIDI裝置設定的發聲數上限為止. Omni-On則是MIDI裝置對MIDI訊息作反應但忽略channel的指定; Mono會使MIDI裝置最多只發出一個聲音.
(三)、MIDI message
MIDI message可以分成channel message, system exclusive, system common和system real-time這幾種. 每個MIDI message都有一個status byte, 代表這個訊息 (message) 的種類. 如果是channel message的話, status byte還包含了"這是第幾個channel"的訊息. 在status byte之後通常會有1 ~ 2個byte的data byte, 儲存這一項訊息所需要的相關資料. 所以一個MIDI message要佔1 ~ 3 bytes.
下面是Note On的channel message, 代表在channel 1發出中央Do的聲音, 力度是100. 其中Status Byte 9nh的n代表是第幾個channel, 表格中的數字以16進位表示.
Status Byte
Data Byte
Data Byte
Note On
9nh
音高
力度
例.
90h
3Ch
64h
下面是Control Change - Main Volume的channel message, 可將channel 9的Main Volume定成90.
Status Byte
Data Byte
Data Byte
Control Change
Bnh
Control number
Data
例. Main Volume
B8h
07h
5Ah
音符的記錄
前面提到過Note On, 另外當然還有Note Off, 不然已經發出的聲音就沒辦法關掉了! 但是裡面只定義了音高和力度, 那麼剩下的音長 (duration) 在哪裡呢? 其實MIDI還包含了時間參考單位, 這一部分我打算簡單的介紹就好, 如果詳細解釋的話, 各位可能就要睡著了...
首先是MIDI Timing Clock, 在每一個四分音符長度中會跳24次, 所以如果一首曲子的速度很快的話, MIDI Timing Clock也會跟著變快. 但是24次的"解析度"沒有辦法符合所有人的需求, 所以編曲軟體或硬體 (sequencer) 通常會細分成120, 384, 480...等更高的解析度. 如果在不同的時間單位裡面放置Note On和Note Off, 就可以記錄不同的音長.
再來是SMPTE Time Code和MIDI Time Code, 它們的產生有著一定的頻率, 不隨曲子快慢而變動, 也用來當作時間單位的參考.
Multi-timbral如果有一台合成器能夠同時發出兩種以上不同的聲音 (音色), 則我們稱這台合成器為multi-timbral instrument. 另外我們可以看到有的合成器規格上寫著"Multi-timbral: 16," 意思就是它可以同時產生16種不同的音色.
最後請記得MIDI只是一種溝通介面, 有MIDI的不一定是合成器, 像效果器也可以有MIDI; 另外也不是所有的合成器都有MIDI, 在MIDI規格制定前生產的合成器就沒有MIDI介面.
資料參考來源:
Stairway to Heaven
Exploring MIDI
Hope Net雜誌1995年7月號
英文Sythesizer這個詞在英文裏的意思是綜合、用合成法合成與綜合處理的意思。合成器通過一定的原理生成波形,然後再由使用者來改變聲音的某些特性。最初電子樂器中採用的是類比式電子合成器。它是通過對震盪器的控制來實現的,電壓控制震盪器是通過改變電壓大小控制震盪頻率的電子電路(VCO),而由此產生的震盪信號還需要再加入調製信號來進行各種樂器效果,然後由電壓控制放大器(VCA)來完成對音量的控制。同時為了使得模擬合成器具備真實樂器的特性,通常要通過包絡(或波封)來控制VCO的幅度特性。最常見的包絡包含四個基本的係數,即ADSR:
1、 Attack:起音,類比鍵盤彈下後聲音升高的速率,可以比較好的體現觸鍵的效果;
2、 Decay:衰減,聲音升到最高峰後回落的速率;
3、 Sustain:延音,決定了鍵按下去後聲音的延遲長度;
4、 Release:釋音,鍵放開後聲音結束的速度。
當然,通過包絡來控制聲音屬性是遠遠不夠的,隨著電子合成器的不斷發展,出現了更多的原來自然或相對傳統合成器中所沒有的音色,濾波器的作用也就越來越明顯了,它可以用來改變聲音中的頻率成分構成。
通過以上簡單的介紹,大家應該明白為什麼現在那"玩意"叫合成器了吧?
那麼數位式合成器和類比式合成器有什麼不同呢?數位式合成器不是由電子元器件製成的信號發生器來產生聲音中的各種頻率成分,而是直接由數位的方法來造出的波形,然後轉換為聲音資訊。這樣的話,數位式合成器的波形即可以是採樣的,也可以是數學方程的計算!!
讓我們來看一下電子合成器的組成圖:
由上圖可知,其實數位式合成器就是一台特殊的電腦,也是軟硬體的綜合體。
下面介紹一下聲音的合成方法:
1、 類比電子合成器
類比電子合成器又分為兩種合成方法:
A、 減法合成器,早期的類比電子合成器中有很大一部分是由減法合成器產生聲音的。它的原理是,用複雜的波形作為樣本,然後按照要產生聲音的波形的頻率情況,即目標波形的要求,把樣本波形中的一些頻率濾除,從而產生不同的目標波形。
B、 加法合成器,同減法合成器相比,加法合成器是一種更為複雜的合成方法,它首先由基本波形出發,然後按照目標波形的要求把不同頻率的泛音加入基本波形,產生聲波的和諧共振,從而產生不同的音色。
2、數位合成法
數字式合成器也簡單分為兩大類
A、數位FM合成法,數位FM合成法是在70年代由斯坦福大學開發出來的一種數位式電子合成器方法。FM是採用頻率調製的方法,通過一些波形(調製信號)改變載波頻率的相位來實現上述運算式。根據其原理,從原理上來說可以類比任何聲音信號。
B、採樣重播合成法,與前面的FM合成法不同的是,它的波形不是由震盪器產生的基本波形,而是通過實際錄製樂器而得來的波形。它的原理是,首先從一種樂器中取下一個或多個週期的波形作為基礎,然後確定該週期的起點和終點,對該取樣波形的振幅進行處理和測試,以滿足聲音重播的要求。用傳統的波封來調整波形的振幅,以模擬自然樂器自然演奏時的效果,對波形進行頻率進行濾波等再處理,然後把波形和相應的合成係數寫入電子合成器的ROM記憶體中,由於這些波形及合成係數是以波形表形式存儲在合成器的ROM中,所以採樣合成器又程波表合成器。
Let's examine the 6 data bytes (which follow the MThd header) in an MThd chunk.
The first two data bytes tell the Format (which I prefer to call "type"). There are actually 3 different types (ie, formats) of MIDI files. A type of 0 means that the file contains one single track containing midi data on possibly all 16 midi channels. If your sequencer sorts/stores all of its midi data in one single block of memory with the data in the order that it's "played", then it should read/write this type. A type of 1 means that the file contains one or more simultaneous (ie, all start from an assumed time of 0) tracks, perhaps each on a single midi channel. Together, all of these tracks are considered one sequence or pattern. If your sequencer separates its midi data (i.e. tracks) into different blocks of memory but plays them back simultaneously (ie, as one "pattern"), it will read/write this type. A type of 2 means that the file contains one or more sequentially independant single-track patterns. If your sequencer separates its midi data into different blocks of memory, but plays only one block at a time (ie, each block is considered a different "excerpt" or "song"), then it will read/write this type.
The next 2 bytes tell how many tracks are stored in the file, NumTracks. Of course, for format type 0, this is always 1. For the other 2 types, there can be numerous tracks.
The last two bytes indicate how many Pulses (i.e. clocks) Per Quarter Note (abbreviated as PPQN) resolution the time-stamps are based upon, Division. For example, if your sequencer has 96 ppqn, this field would be (in hex):
00 60
NOTE: The 2 bytes that make up the Division are stored in (Motorola) "Big Endian" byte order, not (Intel) "Little Endian" reverse byte order. The same is true for the NumTracks and Format.
Alternately, if the first byte of Division is negative, then this represents the division of a second that the time-stamps are based upon. The first byte will be -24, -25, -29, or -30, corresponding to the 4 SMPTE standards representing frames per second. The second byte (a positive number) is the resolution within a frame (ie, subframe). Typical values may be 4 (MIDI Time Code), 8, 10, 80 (SMPTE bit resolution), or 100.
You can specify millisecond-based timing by the data bytes of -25 and 40 subframes.
Here's what an MThd chunk looks like if you defined it in C:
struct MTHD_CHUNK{ /* Here's the 8 byte header that all chunks must have */ char ID[4]; /* This will be 'M','T','h','d' */ unsigned long Length; /* This will be 6 */ /* Here are the 6 bytes */ unsigned short Format; unsigned short NumTracks; unsigned short Division;};
And here's an example of a complete MThd chunk (with header) if you examined it in a hex editor:
來源:
http://home.roadrunner.com/~jgglatt/tech/midifile/mthd.htm
首先是Track的結構:
│event │event │event │event │event │
我們看到MIDI Event(midi message)是被包在Track裏面的。
再來看MIDI Event的結構:
其中status byte中最高的4個bit代表message type,最低的4個bit代表channel,所以反而channel的資料是跟著每一個event在跑,換句話說,在同一個track裏面,如果你不同的note要給予不同的channel,還是可以的。
而format 0,只不過是file中只有一個track,但是你每個event要從那個channel送出來,都可以!!
http://tw.myblog.yahoo.com/scopasia-music/article?mid=670
A standard MIDI file is composed of "chunks". It starts with a header chunk and is followed by one or more track chunks. The header chunk contains data that pertains to the overall file. Each track chunk defines a logical track.
SMF = <header_chunk> + <track_chunk> [+ <track_chunk> ...]
A chunk always has three components, similar to Microsoft RIFF files (the only difference is that SMF files are big-endian, while RIFF files are usually little-endian). The three parts to each chunk are:
Header Chunk
The header chunk consists of a literal string denoting the header, a length indicator, the format of the MIDI file, the number of tracks in the file, and a timing value specifying delta time units. Numbers larger than one byte are placed most significant byte first.
header_chunk = "MThd" + <header_length> + <format> + <n> + <division>
1 = multiple track file format
2 = multiple song file format (i.e., a series of type 0 files)
Track Chunk
A track chunk consists of a literal identifier string, a length indicator specifying the size of the track, and actual event data making up the track.
track_chunk = "MTrk" + <length> + <track_event> [+ <track_event> ...]
Track Event
A track event consists of a delta time since the last event, and one of three types of events.track_event = <v_time> + <midi_event> | <meta_event> | <sysex_event>
Meta Event
Meta events are non-MIDI data of various sorts consisting of a fixed prefix, type indicator, a length field, and actual event data..meta_event = 0xFF + <meta_type> + <v_length> + <event_data_bytes>
System Exclusive Event
A system exclusive event can take one of two forms:sysex_event = 0xF0 + <data_bytes> 0xF7 or sysex_event = 0xF7 + <data_bytes> 0xF7
In the first case, the resultant MIDI data stream would include the 0xF0. In the second case the 0xF0 is omitted.
Variable Length Values
Several different values in SMF events are expressed as variable length quantities (e.g. delta time values). A variable length value uses a minimum number of bytes to hold the value, and in most circumstances this leads to some degree of data compresssion.A variable length value uses the low order 7 bits of a byte to represent the value or part of the value. The high order bit is an "escape" or "continuation" bit. All but the last byte of a variable length value have the high order bit set. The last byte has the high order bit cleared. The bytes always appear most significant byte first.
Here are some examples:
Variable Length Values
http://253.ccarh.org/handout/vlv/
Goto: [ motivation | definition | examples ]
Motivation for Variable Length Values
Standard MIDI Files contain MIDI data.
However, MIDI data by itself is not useful to store unless you also store/record a time associated with that MIDI data.
Therefore, Standard MIDI Files contain at the top level things called events. Each event consists of two components: a time, and a MIDI message. These time/message pairs follow each other one after another in a MIDI file, so the order of data in a MIDI file goes like this in one long stream:
The time value is a measurement of the time to wait before playing the next message in the stream of MIDI file data. This method of specifying the time is called delta time, where delta is a jargon term in mathematics and related fields which means "difference" -- so a delta time is a time value which specifies the duration (or time difference) between two events.
Now note that MIDI messages usually come after each other quickly -- especially if there are chords. So the predominant time between each MIDI message in a MIDI file is going to be small.
MIDI files, like plain MIDI data, are stored in the form of bytes. Bytes can be though of as numbers in the range from 0 to 255, since a byte is a binary number with 8 digits, which can store numbers from 00000000 to 11111111.
This poses a problem in binary data such as MIDI files. The MIDI file is just a stream of numbers, each of which is in the range from 0 to 255. How do you tell when a time or message starts/stops? For example, here is some data from a MIDI file (in hexadecimal notation):
How do you separate this stream of data into time/message pairs? If you don't know anything about MIDI, you are in the same position as a computer who is reading this data. In order to to the segretation into time/data pairs you have to know the MIDI Protcol and about Variable Length Values. Once you have a basic understanding of MIDI files, you should be able to distinguish the time/message pairs with hardly any effort:
Notice that time values sometime are two bytes in length, and sometimes they are one byte in length. Using more than one byte for the delta time implies a longer time value. Time values in a MIDI file are stored as Variable Length Values (VLV). A VLV is a number with a variable width
I won't explain how to segment the MIDI message data here, but here is a simple algorithm for parsing a VLV value out of a byte stream:
Why use VLV's? Why not use time values which are stored in fixed number of bytes which can store the maximum delta-time necessary? This is possible, and perhaps preferrable since this would make things easier. Then the byte stream in a MIDI file might look like this:
The people who designed the structure of the Standard MIDI file were concerned about storage space. The MIDI protocol was created in the early 1980's when PC computers often didn't have hard disks, and the floopy disks contains 256KB of information max. Now in the year 1999, a 1GB hard disk is considered small (which could hold around 5,000 256KB floppies on it). We can't easily change the MIDI file format now however, because there are lots of MIDI files and programs that read MIDI files which would become obsolete for no significant improvement in the file format other than to make it easier for humans to read (which they shouldn't be doing anyway).
Since delta times are usually small, we can use just one byte usually to store the time. However if delta times are large, then more than one byte is needed to store the delta time. Therefore, by using VLV's, the size of a MIDI file is reduced. So, you can think of VLV's as a form of compression.
Definition of Variable Length Values
A MIDI file Variable Length Value is stored in bytes. Each byte has two parts: 7 bits of data and 1 continuation bit. The highest-order bit is set to 1 if there is another byte of the number to follow. The highest-order bit is set to 0 if this byte is the last byte in the VLV.
To recreate a number represented by a VLV, first you remove the continuation bit and then concatenate the leftover bits into a single number.
To generate a VLV from a given number, break the number up into 7 bit units and then apply the correct continuation bit to each byte.
In theory, you could have a very long VLV number which was quite large; however, in the standard MIDI file specification, the maximum length of a VLV value is 5 bytes, and the number it represents can not be larger than 4 bytes.
Examples
The MIDI file delta-time 0h can be represented as a byte like this:
This is a variable length value with a length of one byte.First segretate the continuation bit from the data bits for the value:
What is the continuation bit? It is zero. This means that there are no more bytes to follow this byte for the delta time's value. Now look and figure out what number they are. 0000000 in binary notation is equal to 0 hex, or 0 decimal.
Therefore the VLV 00000000 is equal to 0.
Now look at a harder example: 81 00 (hex).
Since 81 is larger than 80, you can see that the 00 byte is also part of the VLV. Lets look at 81 00 in binary notation:
Separate the continuation bit from the data bits:
Now you can see in binary notation what you can also see in hex notation -- that the first byte expects at least one more byte to follow it in the VLV. Remove the continuation bits:
This is the actual number that is represented by the VLV value 81 00, but maybe we should convert to decimal or hex so you understand it better. First, combine all of the bits into one clump:
I will convert first to hexadecimal, and later to decimal. For hexadecimal conversion of a binary number, arrange the digits into groups of 4, starting with the least siginificant (smallest, right) side of the number:
There are two zeros left on the left size, so add two more zeros to make a grouping of four digits:
We can do this in decimal notation to show why this can be done: the number 0045 and 45 are the same number. Now, convert the binary groupings into hexadecimal digits:
Therefore the number is 0080 or 80 in hex notation. Convert 80 to decimal notation:
Here is the same data as listed in the motivation section, but with the delta times convered to decimal numbers
What are the units of measurements for delta times? In a MIDI file, the units are arbitrary, and you have to look at the header of the MIDI file to see what the units mean. For this example, the time units are 128 ticks to the quarter note, so 128 is a quarter note duration, 256 is a half-note, and 64 is an eighth-note duration.
For the class, you can use the program vlv to convert between variable length values and the numbers that they represent (or vice-versa).
Here are some more equivalences between VLV's and the number they represent:
-- Craig Stuart Sapp
MiDi升降音的學問還蠻大的,不過還好我找到了一段珍貴的參考code. 可以用來抄成C++版本.
下面的array是對應到transpose函式中帶入的mode[]陣列, 可以決定升降key的模式.平均升,全升,或是某些key升, 可以有
不同的效果
public static final int[]
CHROMATIC_SCALE = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
MAJOR_SCALE = {0, 2, 4, 5, 7, 9, 11},
MINOR_SCALE = {0, 2, 3, 5, 7, 8, 10},
HARMONIC_MINOR_SCALE = {0, 2, 3, 5, 7, 8, 11},
MELODIC_MINOR_SCALE = {0, 2, 3, 5, 7, 8, 9, 10, 11}, // mix of ascend and descend
NATURAL_MINOR_SCALE = {0, 2, 3, 5, 7, 8, 10},
DIATONIC_MINOR_SCALE = {0, 2, 3, 5, 7, 8, 10},
AEOLIAN_SCALE = {0, 2, 3, 5, 7, 8, 10},
DORIAN_SCALE = {0, 2, 3, 5, 7, 9, 10},
LYDIAN_SCALE = {0, 2, 4, 6, 7, 9, 11},
MIXOLYDIAN_SCALE = {0, 2, 4, 5, 7, 9, 10},
PENTATONIC_SCALE = {0, 2, 4, 7, 9},
BLUES_SCALE = {0, 2, 3, 4, 5, 7, 9, 10, 11},
TURKISH_SCALE = {0, 1, 3, 5, 7, 10, 11},
INDIAN_SCALE = {0, 1, 1, 4, 5, 8, 10};
/**
* Transpose the phrase up or down in scale degrees.
*
* <P> If <CODE>note</CODE> is null then this method does nothing. If the
* transposition shifts a pitch above {@link Note#MAX_PITCH MAX_PITCH} or
* below {@link Note#MIN_PITCH MIN_PITCH}, the pitch will probably cap at
* those values. See the description of {@link Note#setPitch} method for
* exact details of what occurs when trying to set the pitch beyond the
* allowed range.
*
* Transposition is in diatonic steps. For example in C major the note C
* transposed 1 will become D, transposed 4 will become G, and transposed
* by 7 will beome C an octave above. This can be somewhat unintuitive
* so be careful.
*
* @param note Note to be transposed
* @param transposition the amount to transpose in semitones
* @param mode the scale to use for the transposition
* (the JMC has some scale constants)
* @param key the chromatic note to be used as the root
* of the mode. i.e., 0 = C, 1 = C# etc.
*/
public static void transpose(Note note, final int transposition, final int[] mode, int key) {
try {if (note == null)new NullPointerException();
}catch(NullPointerException e) {e.printStackTrace();}
int pitch = note.getPitch();
if (pitch != Note.REST) {
// work out the original scale octave, degree and accidental
int octave = pitch / 12;
int accidental = 0;
Note n = note.copy();
while (!n.isScale(mode)) {
n.setPitch(n.getPitch() -1);
accidental++;
}
int degree = 0;
for (int i = 0; i < mode.length; i++) {
if (pitch%12 - accidental == mode[i]) {
degree = i;
i = mode.length; // break out of loop next time
}
}
// calculate the new pitch
int newDegree = degree + transposition;
while (newDegree >= mode.length) {
octave++;
newDegree -= mode.length ;
}
while (newDegree < 0) {
octave--;
newDegree += mode.length;
}
note.setPitch(mode[newDegree] + octave * 12 + accidental);
}
}
(四) 卡拉OK升降 key
一般我們聽到的演奏曲很少升降key.作曲者參考樂器含蓋的音域與音色及演奏方法,定下曲子的調.有些樂器在音域範圍內可以任意轉調,例如以十二平均律訂定音程的鋼琴或是指板沒有固定按壓位置而可以奏出連續音階的提琴類,除了演奏指法改變,基本上都可以升降轉調.但是有些樂器採特定音程,如古箏採用中國五聲音階,口琴採用七聲音階,它們都無法輕易轉調.不能轉調的樂器在合奏時就必需用特殊方法克服,例如多準備幾把不同調的樂器替換使用.
在西洋古典音樂,一般的作曲者會把樂器配置考慮進去,樂譜清楚載明使用樂器和調性.例如我們會看到”孟德爾頌E小調小提琴協奏曲”這樣的曲名,把曲子的調性和配置標示得很清楚.幾乎不容許演奏者作任何更動.
人聲這樣樂器很特別,生長在每個人身上.氣由肺部送到喉部使聲帶震動而發出聲音.目前透過聲紋鑑定,沒有兩個人會完全相同.音色不相同,音域也不盡相同. 當一首好歌受到認同,有多人都想要唱,就可能為了音域的關係,必需移到適合演唱者的調.因此雖然歌曲的作曲者標了參考調性,演唱者卻很可能加以調整.
有些人對歌曲只唱原唱者原key不然就捨棄.這樣的方式不恰當.唱歌是藝術美學的一種,應該要儘量讓它悅耳好聽.唱在適合你的調一定會加分.在民視的明日之星歌唱比賽節目中,主審丁曉雯問唱出高分(94)的衛冕者鄭如儀:[”斷了線”這首歌有沒有嘗試降1key?].她的回答是”沒有”.她覺得柯以敏的原key可以唱就唱了.丁老師說出了重點,當你音域很寬可能很多key都能唱,但是只有一個key是最對味的,唱起來是最游刃有餘最能表現情感的,那才是正確的key.丁老師後來讓她降一key試看看,果然副歌高音部份駕馭的更好效果更棒.這一段表演與講評有網友PO到Youtube,有興趣可到下列網址覽 : http://www.youtube.com/watch?v=zJDyHtqexdA
調key 有可能是把超出自己音域外的音樂調回到可以駕馭的key. 另外一個原因就是雖然演唱者音域夠寬都可以唱,但是要找到最適合最好的key. 有關這方面的討論,張欽銘學長在我們的聚會中, 曾經多次分享他精闢的心得.讓大家獲益良多.
接下來我想討論不同系統間升降key的對應. 假如你唱的是同一系統,已經相當熟練, 恭喜你 ! 只要把最適合的調是升降幾個key找到,相同的版本相同的點歌機,保證妥當.
要是換了另外一個系統,要如何對應? 假如系統會顯示絕對調性(可以看到顯示 Dm / G / C …等等) 如 金嗓/弘音/點將家/音圓…的MIDI系統,在找到適合的調性的同時,務必把它的絕對調號(Dm / G / C ….)記在本子或腦袋瓜裡. 你只要告訴DJ要唱的調號,就可對應一致.
某些點歌機有升降key音程限制,也許無法升/降到你要的key. 這時候可以嘗試原來要升key的改為降key,要降key的改為升key,看看可不可以找到要的key. 不然只能升/降到它的極限拼看看,再不行就山不轉路轉,換一首歌唱(活人怎麼可以讓尿憋死,不要死心眼). 儘量不要記 男key +2 ,女key -1這一類, 除非你很執著就只準備要唱單一個系統.
剛剛提到升降key互換的問題. 一個音把響應頻率提高一倍稱為高八度 (用七聲音階來算,本身算一度,唱名為Do-Re-Mi-Fa-So-La-Si-Do ,對應音名為C-D-E-F-G-A-B-C 之間是八度). 其中 E-F & B-C 是半個音程,其他相鄰音的音程是它的兩倍:一個全音程. 在一個八度內會含12個半音階(C,#C,D,#D,E,F,#F,G,#G,A,#A,B 或C, bD,D,bE,E,F,bG,G,bA,A,bB,B ),我們講升降1key,通常是升降半個音(也有少數不是).
假如伴唱音樂和我們唱出來的人聲在同一音高,那最好,但是假如伴唱音樂比人聲高八度或低八度,一般仍然可以適應. 假如把音樂升6key和降6key比較剛好差12個半音,也就是差一個八度. 所以我們要升4key也可以降8key,要降5key也可以升7key.這是理論面,實際上點唱機有升降key數目限制,不一定要升降幾key就可以升降幾key.另外升降的音程過大,數位處理的效果會變差.一般先選升降少key的這邊.通常升key似乎比降key好.
當我們一個升4key和另一個降4key來比較. 直接看是升4key的高降4key的8個key,四個全音.假如把升4key的音降低八度來唱,升4key的反而低了降4key的4個key(兩個全音). 假如降4key的升高八度來唱,反而高升4key的4個key(兩個全音).好像有點複雜又繞舌.還沒清楚就慢慢消化一下. 這就是為何女生的音比較高,但是改男key反而要升4key而不是降key.
接下來是一個困難度比較高的問題.像原聲原影,美華,Bix-Max…等,不會顯示調性的系統要如何對應? 當然還是要找到調性.對於原唱出版品的原聲原影,或許可以找歌譜,或到網路尋求答案. 根本的辦法是自己找.首先需要有可以發出參考音的工具,如樂器(鋼琴,吉他…),音叉,電子調音器,電腦軟體….最好是可調key電子琴.用這些工具比對找出歌曲的最後結束音.假如曲子結束音為G,那這個曲子不是G大調就是G小調.如何判別是大調還小調? 假如那個音當簡譜的 Do 唱就是大調(絕大部份的大調曲子結束在Do), 當簡譜的La唱就是小調(絕大部份的小調曲子結束在La).至於旋律在簡譜怎麼唱,就要靠點經驗.一般來說,簡譜出現大量升降記號很可能有問題,就試另一個看看.也可以用曲式判斷,小調哀怨大調開朗.這還是很抽象.其實大小調有其相關性,音階的排列也不一樣,講這些很複雜.音樂基礎好的很容易分辨大小調.一般沒有音樂基礎的可能就有些困難. 這是我目前可以想到的方法.