MIDI音樂編程那些事兒-創(chuàng)新互聯(lián)

文章目錄
  • 前言
  • 一、Windows系統(tǒng)的 win32 API MIDI函數(shù)
    • 1、win32 API MIDI函數(shù)的獲取
    • 2、MIDI函數(shù)的參數(shù)和返回值
  • 二、MIDI短消息函數(shù)的使用
    • 1、midiOutShortMsg函數(shù)的參數(shù)格式
    • 2、midiOutShortMsg函數(shù)中的命令說明

創(chuàng)新互聯(lián)建站主營烏魯木齊網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,重慶APP軟件開發(fā),烏魯木齊h5微信平臺(tái)小程序開發(fā)搭建,烏魯木齊網(wǎng)站營銷推廣歡迎烏魯木齊等地區(qū)企業(yè)咨詢
前言

新冠疫情期間沒事兒,玩起了音樂和電腦。因?yàn)檎诶美吓f電子琴學(xué)彈 “我愛你中國” (簡譜的眼睛),手上較為完整的曲譜卻是五線譜,無奈!把它翻譯成簡譜。本來想通過電腦幫我把輸入的五線譜轉(zhuǎn)換成指定大調(diào)的簡譜(轉(zhuǎn)成不同調(diào)的簡譜,這do re me 就不一樣了,手工轉(zhuǎn)換很燒腦的),這不需要MIDI的。可是,后來想讓電腦在每轉(zhuǎn)換好一個(gè)音后立刻把音發(fā)出來,然后就有了下面的文章。

一、Windows系統(tǒng)的 win32 API MIDI函數(shù)

在Windows系統(tǒng)中要演奏MIDI音樂,可以通過API函數(shù)進(jìn)行。我們要做的只是調(diào)用它們,并通過它們發(fā)送MIDI消息給Windows,其余的事都由Windows在后臺(tái)完成。為了要調(diào)用API函數(shù),首先要做的就是獲取這些MIDI函數(shù),并了解它們的參數(shù)要求及其返回值?;镜腗IDI函數(shù)有3個(gè):midiOutOpen 、MidiOutShortMsg、MidiOutClose,分別用來打開MIDI設(shè)備、操作MIDI設(shè)備和關(guān)閉MIDI設(shè)備。

1、win32 API MIDI函數(shù)的獲取

Windows的MIDI函數(shù)在系統(tǒng)動(dòng)態(tài)鏈接庫winmm.dll中。在Borland C++ builder環(huán)境中代碼如下:
注:下面的代碼結(jié)合了多位作者的代碼示例才啟發(fā)了我,并且在時(shí)間上也持續(xù)了2-3天,特別是函數(shù)的轉(zhuǎn)換上。所以這里無法給出具體作者,如有作者向我指出,我會(huì)加上其引用。

//在獲取函數(shù)地址前,先說明其在相應(yīng)開發(fā)環(huán)境中的函數(shù)原型
int __stdcall (*MidiOutOpen)(int &hMidiOut, int uDeviceID,int dwCallBack,int dwInstance,int dwFlags);
int __stdcall (*MidiOutClose)(int hMidiOut );
int __stdcall (*MidiOutShortMsg)(int hMidiOut, int dwMsg);


HINSTANCE h=NULL;
int MidiOut=0;
void __fastcall TForm1::FormCreate(TObject *Sender)
{ h=::LoadLibrary("winmm.dll");	//載入動(dòng)態(tài)鏈接庫,LoadLibrary函數(shù)會(huì)自動(dòng)定位其所在目錄
     if(NULL != h) 
     {  MidiOutOpen= (int __stdcall (*)(int &, int,int,int,int)) GetProcAddress(h,"midiOutOpen");
          if( MidiOutOpen==NULL) ShowMessage( "'midiOutOpen' not found in winmm.dll " );

          MidiOutClose = (int __stdcall (*)(int)) GetProcAddress(h,"midiOutClose")   ;
          if( MidiOutClose ==NULL  )  ShowMessage( "'midiOutClose' not found in winmm.dll " );

          MidiOutShortMsg=(int __stdcall (*)(int , int )) GetProcAddress(h,"midiOutShortMsg") ;
          if( MidiOutShortMsg ==NULL  )  ShowMessage( "'midiOutShortMsg' not found in winmm.dll " );

          MidiOutOpen(MidiOut,-1,0,0,0);     //打開MIDI設(shè)備
          //MidiOutShortMsg(MidiOut,0x7BB0);   //停止演奏
          //MidiOutShortMsg(MidiOut,0xC0);     //默認(rèn)樂器為鋼琴
     }
     else 
          ShowMessage( "winmm.dll not found" ) ;
}

以上代碼解釋如下:LoadLibrary函數(shù)是windows函數(shù),用來載入winmm.dll動(dòng)態(tài)鏈接庫到內(nèi)存,并返回其句柄到h(h非空表示載入成功);GetProcAddress函數(shù)是windows API函數(shù),用來從句柄h中獲取指定名稱的函數(shù)在相應(yīng)DLL中的地址,我們對(duì)該指定名稱的函數(shù)的調(diào)用實(shí)際上就是“程序跳轉(zhuǎn)”到該地址,也就是說,該地址就是該函數(shù)。同樣,GetProcAddress返回空表該DLL中沒有指定名稱的函數(shù)(這里嚴(yán)格區(qū)分大小寫)。
除了函數(shù)在DLL中的入口地址還不夠,所以還要強(qiáng)制轉(zhuǎn)換為與相應(yīng)函數(shù)原型具有相同參數(shù)類型、參數(shù)順序和返回值的調(diào)用地址,以便讓系統(tǒng)知道調(diào)用時(shí)如何處理實(shí)參和返回值。如: MidiOutShortMsg=(int __stdcall (*)(int , int )) GetProcAddress(h,“midiOutShortMsg”);GetProcAddress獲取地址后由(int __stdcall (*)(int , int )) 進(jìn)行轉(zhuǎn)換,這個(gè)轉(zhuǎn)換器實(shí)際上是通過去除函數(shù)原型中的所有標(biāo)識(shí)符后得到的。

在 Delphi 環(huán)境中代碼如下:

Function MidiOutOpen(
    var lphMidiOut:integer; uDeviceID,dwCallback,dwInstance,  dwFlags:integer):integer;
    stdcall;far; External 'winmm.dll';
  Function MidiOutClose(hMidiOut:integer):integer; stdcall;far; External 'winmm.dll';
  Function MidiOutShortMsg(hMidiOut,dwMsg:integer):integer;stdcall;far; External 'winmm.dll';
2、MIDI函數(shù)的參數(shù)和返回值

參考上面的三個(gè)函數(shù)原型,顧名思義:MidiOutOpen是打開MIDI輸出設(shè)備、MidiOutClose是關(guān)閉MIDI輸出設(shè)備,分別在開始前和結(jié)束后一次性調(diào)用;MidiOutShortMsg是向MIDI輸出設(shè)備發(fā)短消息。
三個(gè)函數(shù)只有一個(gè)地方是特別的,即MidiOutOpen的第一個(gè)參數(shù) int &hMidiOut(Delphi中為 var lphMidiOut:integer),這個(gè)參數(shù)必須傳地址,通過它帶回MIDI輸出設(shè)備的句柄,以后關(guān)閉時(shí)也關(guān)閉此句柄,發(fā)短消息也是針對(duì)此句柄,所以一般情況下,保存這個(gè)句柄的變量應(yīng)該為全局變量。
三個(gè)函數(shù)執(zhí)行成功則返回值0,否則返回錯(cuò)誤代碼。
三個(gè)函數(shù)的調(diào)用方式為:
int MidiOut=0;
MidiOutOpen(MidiOut,-1,0,0,0); //打開MIDI設(shè)備,成功則MidiOut為MIDI設(shè)備的句柄,
//否則不要使用MidiOut變量,它是沒有意義的。
MidiOutShortMsg(MidiOut, msg); //發(fā)MIDI短消息到MIDI設(shè)備MidiOut
MidiOutClose(MidiOut); //關(guān)閉MIDI設(shè)備MidiOut


二、MIDI短消息函數(shù)的使用

發(fā)MIDI短消息函數(shù)MidiOutShortMsg(MidiOut, int msg)中MIDI消息msg,是一個(gè)4字節(jié)的整數(shù),格式有點(diǎn)復(fù)雜。下面內(nèi)容中的通道概念是受到了一位可能是臺(tái)灣的朋友1的啟發(fā),經(jīng)本人嚴(yán)格測試后對(duì)其進(jìn)行了修正。

1、midiOutShortMsg函數(shù)的參數(shù)格式

midiOutShortMsg( HMIDIOUT hmo,DWORD dwMsg ) 短消息參數(shù)dwMsg的使用格式:

dwMsg是4字節(jié)無符號(hào)整數(shù),分成4個(gè)部分,每個(gè)部分1個(gè)字節(jié):

字節(jié)作用
最高字節(jié)(第3字節(jié))基本不用
字節(jié)2 (第2字節(jié))音量0-0x7F或不用
字節(jié)1 (第1字節(jié))音階0-0x7F或音色
最低字節(jié)(第0字節(jié))命令或狀態(tài)、通道
第0字節(jié)16進(jìn)制高位命令或狀態(tài)0x9/0xC、0xB
第0字節(jié)16進(jìn)制低位通道0-0xF

具體格式如下(16進(jìn)制):

字節(jié)3字節(jié)2字節(jié)1字節(jié)0功能
00-音色值CN為通道N指定一個(gè)音色值,即選擇一個(gè)樂器,樂器有128種(見下表)
00音量值音階值9N在通道N上,使用指定音量,演奏一個(gè)即定樂器的指定音階
00-0x7BBN停止通道N上的演奏

注:經(jīng)過測試“停止演奏”消息還可以是0x78BN、0x7EBN和0x7FBBN

作為補(bǔ)充說明舉例如下:
設(shè)置消息(CN):
midiOutShortMsg(hMidi,16<<8 | 0xC0) //設(shè)置通道0的樂器為 風(fēng)琴
midiOutShortMsg(hMidi, 0<<8 | 0xC1) //設(shè)置通道1的樂器為 大鋼琴
midiOutShortMsg(hMidi,24<<8 | 0xC7) //設(shè)置通道7的樂器為 尼龍弦吉他
midiOutShortMsg(hMidi,40<<8 | 0xCA) //設(shè)置通道10的樂器為 小提琴
最后一行也可以:
midiOutShortMsg(hMidi,40 * 0x100 + 0xCA) //設(shè)置通道10的樂器為 小提琴

演奏消息(9N):
midiOutShortMsg(
hMidi,0x7F<<16 | 60<<8| 0x9A) //在通道10上以最高音量(0x7F)彈一個(gè)中央C(音高60,音名c1)
midiOutShortMsg(
hMidi,0x40<<16 | 72<<8| 0x93) //在通道3上以半高音量(0x40)彈一個(gè)高音do(音高72,音名c2)
midiOutShortMsg(
hMidi,0x40<<16 | 76<<8| 0x94) //在通道4上以半高音量(0x40)彈一個(gè)高音me(音高76,音名e2)
最后一行也可以:
midiOutShortMsg(hMidi,0x40 * 0x10000 + 76 * 0x100 + 0x94) //在通道4上以半高音量(0x40)彈一個(gè)高音me(音高76,音名e2)

停止[演奏]消息(BN):
midiOutShortMsg(hMidi, 0x7BB7) //停止通道7上的演奏
midiOutShortMsg(hMidi, 0x7BB3) //停止通道3上的演奏



MIDI樂器編號(hào)(音色值):2
0 Acoustic Grand Piano 大鋼琴(聲學(xué)鋼琴)
1 Bright Acoustic Piano 明亮的鋼琴
2 Electric Grand Piano 電鋼琴
3 Honky-tonk Piano 酒吧鋼琴
4 Rhodes Piano 柔和的電鋼琴
5 Chorused Piano 加合唱效果的電鋼琴
6 Harpsichord 羽管鍵琴(撥弦古鋼琴)
7 Clavichord 科拉維科特琴(擊弦古鋼琴)

8 Celesta 鋼片琴
9 Glockenspiel 鐘琴
10 Music box 八音盒
11 Vibraphone 顫音琴
12 Marimba 馬林巴
13 Xylophone 木琴
14 Tubular Bells 管鐘
15 Dulcimer 大揚(yáng)琴

16 Hammond Organ 擊桿風(fēng)琴
17 Percussive Organ 打擊式風(fēng)琴
18 Rock Organ 搖滾風(fēng)琴
19 Church Organ 教堂風(fēng)琴
20 Reed Organ 簧管風(fēng)琴
21 Accordian 手風(fēng)琴
22 Harmonica 口琴
23 Tango Accordian 探戈手風(fēng)琴

24 Acoustic Guitar (nylon) 尼龍弦吉他
25 Acoustic Guitar (steel) 鋼弦吉他
26 Electric Guitar (jazz) 爵士電吉他
27 Electric Guitar (clean) 清音電吉他
28 Electric Guitar (muted) 悶音電吉他
29 Overdriven Guitar 加驅(qū)動(dòng)效果的電吉他
30 Distortion Guitar 加失真效果的電吉他
31 Guitar Harmonics 吉他和音

32 Acoustic Bass 大貝司(聲學(xué)貝司)
33 Electric Bass(finger) 電貝司(指彈)
34 Electric Bass (pick) 電貝司(撥片)
35 Fretless Bass 無品貝司
36 Slap Bass 1 掌擊Bass 1
37 Slap Bass 2 掌擊Bass 2
38 Synth Bass 1 電子合成Bass 1
39 Synth Bass 2 電子合成Bass 2

40 Violin 小提琴
41 Viola 中提琴
42 Cello 大提琴
43 Contrabass 低音大提琴
44 Tremolo Strings 弦樂群顫音音色
45 Pizzicato Strings 弦樂群撥弦音色
46 Orchestral Harp 豎琴
47 Timpani 定音鼓

48 String Ensemble 1 弦樂合奏音色1
49 String Ensemble 2 弦樂合奏音色2
50 Synth Strings 1 合成弦樂合奏音色1
51 Synth Strings 2 合成弦樂合奏音色2
52 Choir Aahs 人聲合唱“啊”
53 Voice Oohs 人聲“嘟”
54 Synth Voice 合成人聲
55 Orchestra Hit 管弦樂敲擊齊奏

56 Trumpet 小號(hào)
57 Trombone 長號(hào)
58 Tuba 大號(hào)
59 Muted Trumpet 加弱音器小號(hào)
60 French Horn 法國號(hào)(圓號(hào))
61 Brass Section 銅管組(銅管樂器合奏音色)
62 Synth Brass 1 合成銅管音色1
63 Synth Brass 2 合成銅管音色2

64 Soprano Sax 高音薩克斯風(fēng)
65 Alto Sax 次中音薩克斯風(fēng)
66 Tenor Sax 中音薩克斯風(fēng)
67 Baritone Sax 低音薩克斯風(fēng)
68 Oboe 雙簧管
69 English Horn 英國管
70 Bassoon 巴松(大管)
71 Clarinet 單簧管(黑管)

72 Piccolo 短笛
73 Flute 長笛
74 Recorder 豎笛
75 Pan Flute 排簫
76 Bottle Blow [中文名稱暫缺]
77 Shakuhachi 日本尺八
78 Whistle 口哨聲
79 Ocarina 奧卡雷那

80 Lead 1 (square) 合成主音1(方波)
81 Lead 2 (sawtooth) 合成主音2(鋸齒波)
82 Lead 3 (caliope lead) 合成主音3
83 Lead 4 (chiff lead) 合成主音4
84 Lead 5 (charang) 合成主音5
85 Lead 6 (voice) 合成主音6(人聲)
86 Lead 7 (fifths) 合成主音7(平行五度)
87 Lead 8 (bass+lead)合成主音8(貝司加主音)

88 Pad 1 (new age) 合成音色1(新世紀(jì))
89 Pad 2 (warm) 合成音色2 (溫暖)
90 Pad 3 (polysynth) 合成音色3
91 Pad 4 (choir) 合成音色4 (合唱)
92 Pad 5 (bowed) 合成音色5
93 Pad 6 (metallic) 合成音色6 (金屬聲)
94 Pad 7 (halo) 合成音色7 (光環(huán))
95 Pad 8 (sweep) 合成音色8

96 FX 1 (rain) 合成效果 1 雨聲
97 FX 2 (soundtrack) 合成效果 2 音軌
98 FX 3 (crystal) 合成效果 3 水晶
99 FX 4 (atmosphere) 合成效果 4 大氣
100 FX 5 (brightness) 合成效果 5 明亮
101 FX 6 (goblins) 合成效果 6 鬼怪
102 FX 7 (echoes) 合成效果 7 回聲
103 FX 8 (sci-fi) 合成效果 8 科幻

104 Sitar 西塔爾(印度)
105 Banjo 班卓琴(美洲)
106 Shamisen 三昧線(日本)
107 Koto 十三弦箏(日本)
108 Kalimba 卡林巴
109 Bagpipe 風(fēng)笛
110 Fiddle 民族提琴
111 Shanai 山奈

112 Tinkle Bell 叮當(dāng)鈴
113 Agogo [中文名稱暫缺]
114 Steel Drums 鋼鼓
115 Woodblock 木魚
116 Taiko Drum 太鼓
117 Melodic Tom 通通鼓
118 Synth Drum 合成鼓
119 Reverse Cymbal 銅鈸

120 Guitar Fret Noise 吉他換把雜音
121 Breath Noise 呼吸聲
122 Seashore 海浪聲
123 Bird Tweet 鳥鳴
124 Telephone Ring 電話鈴
125 Helicopter 直升機(jī)
126 Applause 鼓掌聲
127 Gunshot


音階值:3

序號(hào)音階值音名序號(hào)音階值音名
121A2
222A2#
323B2
424C15272c2
525C1#5373c2#
626D15474d2
727D1#5575d2#
828E15676e2
929F15777f2
1030F1#5878f2#
1131G15979g2
1232G1#6080g2#
1333A16181a2
1434A1#6282a2#
1535B16383b2
1636C6484c3
1737C#6585c3#
1838D6686d3
1939D#6787d3#
2040E6888e3
2141F6989f3
2242F#7090f3#
2343G7191g3
2444G#7292g3#
2545A7393a3
2646A#7494a3#
2747B7595b3
2848c7696c4
2949c#7797c4#
3050d7898d4
3151d#7999d4#
3252e80100e4
3353f81101f4
3454f#82102f4#
3555g83103g4
3656g#84104g4#
3757a85105a4
3858a#86106a4#
3959b87107b4
4060c1標(biāo)準(zhǔn)鍵盤中央C88108c5
4161c1#
4262d1
4363d1#
4464e1
4565f1
4666f1#
4767g1
4868g1#
4969a1
5070a1#
5171b1

2、midiOutShortMsg函數(shù)中的命令說明

關(guān)于通道的說明:
0-8,0xA,0xB共10個(gè)通道:正常發(fā)聲
9:這個(gè)通道,各個(gè)音階值對(duì)應(yīng)的不是不同音高的音,而是各種打擊樂聲或哨聲
0xC-0xF:這2個(gè)通道發(fā)出的聲音持續(xù)時(shí)間較正常音短(鍵盤和打擊類而言),在演奏鋼琴時(shí)就像沒有踏下踏板一樣

關(guān)于音色的說明:
對(duì)于風(fēng)管類(靠吹氣吹風(fēng)發(fā)聲的)、弓弦類(靠弓拉弦發(fā)聲的)音色,一旦奏響就不會(huì)停下來,必須發(fā)出0x7BBN短消息來停止它;對(duì)于打擊類、鍵盤類和彈撥類音色,在奏響后音量會(huì)漸漸變小直到停下來(也可能是也沒有停下來,只是音量極小聽不到),所以一般情況下演奏和停止消息要成對(duì)發(fā)出,就像括號(hào)一樣,左括號(hào)出現(xiàn)后必須出現(xiàn)右括號(hào)。但在有些情況下可以不使用或不能使用停止消息,如在通道0上用鋼琴彈奏一個(gè)和音時(shí),做法就是連續(xù)發(fā)出3到4個(gè)演奏消息,讓這些音在1個(gè)通道上混響,需要停止該和音時(shí),只要在該通道上發(fā)出單個(gè)停止消息即可。這個(gè)例子也說明:在同一個(gè)通道上是可以發(fā)出N多個(gè)音階的,就像相同樂器的多重奏。



  1. 一位可能是臺(tái)灣朋友問何起的文章 link ??

  2. 音色(樂器)表參考自10年前的網(wǎng)絡(luò)文章,暫無法溯源 ??

  3. 音階表參考自本平臺(tái)韓曙亮的文章 link ??

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

網(wǎng)站題目:MIDI音樂編程那些事兒-創(chuàng)新互聯(lián)
本文網(wǎng)址:http://bm7419.com/article16/hdcgg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、手機(jī)網(wǎng)站建設(shè)、品牌網(wǎng)站制作、企業(yè)建站網(wǎng)站改版、微信小程序

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司