arduino
मिडी संचार
खोज…
परिचय
इस विषय का आशय कुछ बुनियादी मिडी कार्यक्रमों को प्रदर्शित करना है जो दिखाते हैं कि प्रोटोकॉल के साथ कैसे काम करना है और उत्तरोत्तर उपयोगी सुविधाओं को जोड़ना है जिनके लिए अधिक जटिल अनुप्रयोगों की आवश्यकता होती है।
मिडी THRU उदाहरण
मिडी थ्रू सरल और परीक्षण करने में आसान है। जब आप ठीक से काम कर रहे हों, तो आप दो MIDI उपकरणों, MIDI IN से MIDI OUT के बीच अपने Arduino प्रोजेक्ट को स्थापित कर पाएंगे और आप सत्यापित कर पाएंगे कि दोनों डिवाइस एक साथ काम करते हैं। यदि आपके पास विलंबता को मापने की क्षमता है, तो आप सीरियल बफर कैप्चर और पुन: संचारित निर्देशों के कारण वृद्धि देखेंगे।
// This is a simple MIDI THRU. Everything in, goes right out.
// This has been validate on an Arduino UNO and a Olimex MIDI Shield
boolean byteReady;
unsigned char midiByte;
void setup() {
// put your setup code here, to run once:
// Set MIDI baud rate:
Serial.begin(31250);
byteReady = false;
midiByte = 0;
}
// The Loop that always gets called...
void loop() {
if (byteReady) {
byteReady = false;
Serial.write(midiByte);
}
}
// The little function that gets called each time loop is called.
// This is automated somwhere in the Arduino code.
void serialEvent() {
if (Serial.available()) {
// get the new byte:
midiByte = (unsigned char)Serial.read();
byteReady = true;
}
}
कतार के साथ मिडी थ्रू
// This is a more complex MIDI THRU. This version uses a queue. Queues are important because some
// MIDI messages can be interrupted for real time events. If you are generating your own messages,
// you may need to stop your message to let a "real time" message through and then resume your message.
#define QUEUE_DEPTH 128
// Queue Logic for storing messages
int headQ = 0;
int tailQ = 0;
unsigned char tx_queue[QUEUE_DEPTH];
void setup() {
// put your setup code here, to run once:
// Set MIDI baud rate:
Serial.begin(31250);
}
// getQDepth checks for roll over. Folks have told me this
// is not required. Feel free to experiment.
int getQDepth() {
int depth = 0;
if (headQ < tailQ) {
depth = QUEUE_DEPTH - (tailQ - headQ);
} else {
depth = headQ - tailQ;
}
return depth;
}
void addQueue (unsigned char myByte) {
int depth = 0;
depth = getQDepth();
if (depth < (QUEUE_DEPTH-2)) {
tx_queue[headQ] = myByte;
headQ++;
headQ = headQ % QUEUE_DEPTH; // Always keep the headQ limited between 0 and 127
}
}
unsigned char deQueue() {
unsigned char myByte;
myByte = tx_queue[tailQ];
tailQ++;
tailQ = tailQ % QUEUE_DEPTH; // Keep this tailQ contained within a limit
// Now that we dequeed the byte, it must be sent.
return myByte;
}
void loop() {
if (getQDepth>0) {
Serial.write(deQueue());
}
}
// The little function that gets called each time loop is called.
// This is automated somwhere in the Arduino code.
void serialEvent() {
if (Serial.available()) {
// get the new byte:
addQueue((unsigned char)Serial.read());;
}
}
मिडी क्लॉक जेनरेशन
// This is a MiDI clk generator. This takes a #defined BPM and
// makes the appropriate clk rate. The queue is used to let other messages
// through, but allows a clock to go immediately to reduce clock jitter
#define QUEUE_DEPTH 128
#define BPM 121
#define MIDI_SYSRT_CLK 0xF8
// clock tracking and calculation
unsigned long lastClock;
unsigned long captClock;
unsigned long clk_period_us;
// Queue Logic for storing messages
int headQ = 0;
int tailQ = 0;
unsigned char tx_queue[QUEUE_DEPTH];
void setup() {
// Set MIDI baud rate:
Serial.begin(31250);
clk_period_us = 60000000 / (24 * BPM);
lastClock = micros();
}
// getQDepth checks for roll over. Folks have told me this
// is not required. Feel free to experiment.
int getQDepth() {
int depth = 0;
if (headQ < tailQ) {
depth = QUEUE_DEPTH - (tailQ - headQ);
} else {
depth = headQ - tailQ;
}
return depth;
}
void addQueue (unsigned char myByte) {
int depth = 0;
depth = getQDepth();
if (depth < (QUEUE_DEPTH-2)) {
tx_queue[headQ] = myByte;
headQ++;
headQ = headQ % QUEUE_DEPTH; // Always keep the headQ limited between 0 and 127
}
}
unsigned char deQueue() {
unsigned char myByte;
myByte = tx_queue[tailQ];
tailQ++;
tailQ = tailQ % QUEUE_DEPTH; // Keep this tailQ contained within a limit
// Now that we dequeed the byte, it must be sent.
return myByte;
}
void loop() {
captClock = micros();
if (lastClock > captClock) {
// we have a roll over condition - Again, maybe we don't need to do this.
if (clk_period_us <= (4294967295 - (lastClock - captClock))) {
// Add a the ideal clock period for this BPM to the last measurement value
lastClock = lastClock + clk_period_us;
// Send a clock, bypasing the transmit queue
Serial.write(MIDI_SYSRT_CLK);
}
} else if (clk_period_us <= captClock-lastClock) {
// Basically the same two commands above, but not within a roll over check
lastClock = lastClock + clk_period_us;
// Send a clock, bypasing the transmit queue
Serial.write(MIDI_SYSRT_CLK);
}
if (getQDepth>0) {
Serial.write(deQueue());
}
}
// The little function that gets called each time loop is called.
// This is automated somwhere in the Arduino code.
void serialEvent() {
if (Serial.available()) {
// get the new byte:
addQueue((unsigned char)Serial.read());;
}
}
मिडी संदेश परिभाषित
सामान्य तौर पर, MIDI प्रोटोकॉल "संदेशों" में टूट जाता है। संदेशों की 4 सामान्य कक्षाएं हैं:
- चैनल की आवाज
- चैनल मोड
- सिस्टम कॉमन
- सिस्टम रीयल-टाइम संदेश
संदेश 0x80 से ऊपर बाइट मान से शुरू होते हैं। 0x7F से नीचे के किसी भी मूल्य को डेटा माना जाता है। प्रभावी रूप से अर्थ है कि 127 अधिकतम मूल्य है जिसे एक एकल मिडी डेटा बाइट में एन्कोड किया जा सकता है। बड़े मूल्यों को एनकोड करने के लिए दो या अधिक मिडी डेटा बाइट्स की आवश्यकता होती है।
यह ध्यान दिया जाना चाहिए कि संदेशों को बिना किसी रुकावट के पूरा करने के लिए प्रारंभ भेज दिया जाना चाहिए ... EXCEPT ... सिस्टम रियल-टाइम संदेश, जो एक एकल बाइट है, जिसे किसी भी संदेश के बीच में इंजेक्ट किया जा सकता है।
चैनल वॉयस मैसेजेस
स्थिति D7..D0 | डेटा बाइट्स | विवरण |
---|---|---|
1000nnnn | 0kkkkkkkk 0vvvvvvv | नोट बंद घटना। यह संदेश तब भेजा जाता है जब एक नोट जारी किया जाता है (समाप्त)। (kkkkkkk) कुंजी (नोट) संख्या है। (vvvvvvv) वेग है। |
1001nnnn | 0kkkkkkkk 0vvvvvvv | नोट घटना पर। यह संदेश तब भेजा जाता है जब कोई नोट उदास (प्रारंभ) होता है। (kkkkkkk) कुंजी (नोट) संख्या है। (vvvvvvv) वेग है। |
1010nnnn | 0kkkkkkkk 0vvvvvvv | पॉलीफोनिक कुंजी दबाव (आफ्टरचू)। यह संदेश अक्सर "बॉटम्स आउट" के बाद कुंजी को नीचे दबाकर भेजा जाता है। (kkkkkkk) कुंजी (नोट) संख्या है। (vvvvvvv) दबाव मान है। |
1011nnnn | 0cccccc 0vvvvvvv | नियंत्रण बदलें। नियंत्रक मान में परिवर्तन होने पर यह संदेश भेजा जाता है। नियंत्रकों में पैडल और लीवर जैसे उपकरण शामिल हैं। नियंत्रक संख्या 120-127 "चैनल मोड संदेश" (नीचे) के रूप में आरक्षित हैं। (ccccccc) नियंत्रक संख्या (0-119) है। (vvvvvvv) नियंत्रक मान (0-127) है। |
1100nnnn | 0ppppppp | कार्यक्रम बदलें। पैच नंबर बदलने पर यह संदेश भेजा गया। (ppppppp) नया प्रोग्राम नंबर है। |
1101nnnn | 0vvvvvvv | चैनल दबाव (आफ्टर-टच)। यह संदेश अक्सर "बॉटम्स आउट" के बाद कुंजी को नीचे दबाकर भेजा जाता है। यह संदेश पॉलीफेनिक आफ्टर-टच से अलग है। इस संदेश का उपयोग करने के लिए सबसे बड़ा दबाव मूल्य (सभी मौजूदा उदास कुंजी के) भेजने के लिए। (vvvvvvv) दबाव मान है। |
1110nnnn | 0lllll 0mmmmmmm | पिच बेंड चेंज। यह संदेश पिच बेंडर (पहिया या लीवर, आमतौर पर) में बदलाव का संकेत करने के लिए भेजा जाता है। पिच बेंडर को चौदह बिट मान से मापा जाता है। केंद्र (कोई पिच परिवर्तन नहीं) 2000H है। संवेदनशीलता रिसीवर का एक कार्य है, लेकिन आरपीएन 0. (lllllll) का उपयोग करके सेट किया जा सकता है कम से कम 7 बिट महत्वपूर्ण हैं। (mmmmmmm) सबसे महत्वपूर्ण 7 बिट्स हैं। |
चैनल मोड संदेश
स्थिति D7..D0 | डेटा बाइट्स | विवरण |
---|---|---|
1011nnnn | 0cccccc 0vvvvvvv | चैनल मोड संदेश। यह कंट्रोल चेंज (ऊपर) जैसा ही कोड है, लेकिन मोड कंट्रोल और स्पेशल मैसेज कंट्रोल करता है जो रिजर्व्ड कंट्रोलर नंबर 120-127 का इस्तेमाल करता है। आदेश हैं: |
सभी ध्वनि बंद। जब ऑल साउंड ऑफ प्राप्त होता है तो सभी ऑसिलेटर बंद हो जाएंगे, और उनके वॉल्यूम लिफाफे जल्द से जल्द शून्य पर सेट हो जाएंगे। c = 120, v = 0: ऑल साउंड ऑफ | ||
सभी नियंत्रकों को रीसेट करें। जब सभी नियंत्रकों को रीसेट किया जाता है, तो सभी नियंत्रक मान उनके डिफ़ॉल्ट मानों पर रीसेट हो जाते हैं। (डिफॉल्ट के लिए विशिष्ट अनुशंसित अभ्यास देखें)। | ||
c = 121, v = x: मान केवल शून्य होना चाहिए जब तक कि किसी विशिष्ट अनुशंसित अभ्यास में अन्यथा अनुमति न हो। | ||
स्थानीय नियंत्रण। जब स्थानीय नियंत्रण बंद होता है, तो किसी दिए गए चैनल पर सभी डिवाइस केवल MIDI पर प्राप्त डेटा का जवाब देंगे। बजाए गए डेटा, आदि की अनदेखी की जाएगी। स्थानीय नियंत्रण सामान्य नियंत्रकों के कार्यों को पुनर्स्थापित करता है। | ||
c = 122, v = 0: स्थानीय नियंत्रण बंद | ||
c = 122, v = 127: स्थानीय नियंत्रण पर | ||
सभी नोट बंद। जब सभी नोट बंद हो जाते हैं, तो सभी ऑसिलेटर बंद हो जाएंगे। | ||
c = 123, v = 0: सभी नोट्स बंद (वास्तविक मोड कमांड के विवरण के लिए पाठ देखें।) | ||
c = 124, v = 0: ओमनी मोड ऑफ | ||
c = 125, v = 0: ओमनी मोड ऑन | ||
c = 126, v = M: मोनो मोड ऑन (पॉली ऑफ) जहां एम चैनलों की संख्या (ओमनी ऑफ) या 0 (ओमनी ऑन) है | ||
c = 127, v = 0: पॉली मोड ऑन (मोनो ऑफ़) (नोट: ये चार संदेश भी सभी नोट बंद हो जाते हैं) |
सिस्टम कॉमन मैसेज
स्थिति D7..D0 | डेटा बाइट्स | विवरण |
---|---|---|
11110000 | 0iiiiiii [0iiiiiii 0iiiiiii] 0ddddddd --- --- 0ddddddd 11111111 | सिस्टम एक्सक्लूसिव। यह संदेश प्रकार निर्माताओं को अपने स्वयं के संदेश (जैसे बल्क डंप, पैच पैरामीटर और अन्य गैर-विशिष्ट डेटा) बनाने की अनुमति देता है और अतिरिक्त MIDI विनिर्देश संदेश बनाने के लिए एक तंत्र प्रदान करता है। निर्माता का आईडी कोड (MMA या AMEI द्वारा निर्दिष्ट) या तो 1 बाइट (0iiiiiii) या 3 बाइट्स (0iiiiiii 0iiiii 0iiiiii) है। 1 बाइट आईडी में से दो यूनिवर्सल एक्सक्लूसिव मैसेज नामक एक्सटेंशन के लिए आरक्षित हैं, जो निर्माता-विशिष्ट नहीं हैं। यदि कोई डिवाइस आईडी कोड को अपना (या समर्थित यूनिवर्सल संदेश के रूप में) पहचानता है, तो वह शेष संदेश (0ddddddd) को सुनेगा। अन्यथा, संदेश को नजरअंदाज कर दिया जाएगा। (नोट: केवल रीयल-टाइम संदेशों को सिस्टम एक्सक्लूसिव के साथ इंटरलेक्ट किया जा सकता है।) |
11110001 | 0nnndddd | मिडी टाइम कोड क्वार्टर फ़्रेम। nnn = संदेश प्रकार dddd = मान |
11110010 | 0lllll 0mmmmmmm | गीत स्थिति सूचक। यह एक आंतरिक 14 बिट रजिस्टर है जो गाने की शुरुआत के बाद से मिडी बीट्स (1 बीट = छह मिडी घड़ियों) की संख्या रखता है। एल एलएसबी है, एम एमएसबी है। |
11110011 | 0sssssss | गीत का चयन करें। सॉन्ग सलेक्ट निर्दिष्ट करता है कि कौन सा सीक्वेंस या गाना बजाया जाना है। |
11110100 | अपरिभाषित। (आरक्षित) | |
11110101 | अपरिभाषित। (आरक्षित) | |
11110110 | धुन अनुरोध। ट्यून अनुरोध प्राप्त करने पर, सभी एनालॉग सिंथेसाइज़र को अपने ऑसिलेटर्स को ट्यून करना चाहिए। | |
11110111 | अनन्य का अंत। सिस्टम अनन्य डंप को समाप्त करने के लिए उपयोग किया जाता है (ऊपर देखें)। |
सिस्टम रीयल-टाइम संदेश
स्थिति D7..D0 | डेटा बाइट्स | विवरण |
---|---|---|
11111000 | घड़ी का समय। 24 बार प्रति तिमाही नोट भेजा गया जब सिंक्रनाइज़ेशन की आवश्यकता है (पाठ देखें)। | |
11111001 | अपरिभाषित। (आरक्षित) | |
11111010 | शुरू। वर्तमान अनुक्रम खेल शुरू करें। (इस मैसेज को टाइमिंग क्लॉक्स के साथ फॉलो किया जाएगा)। | |
11111011 | जारी रखें। अनुक्रम रुक गया था बिंदु पर जारी रखें। | |
11111100 | रूक जा। वर्तमान अनुक्रम को रोकें। | |
11111101 | अपरिभाषित। (आरक्षित) | |
11111110 | सक्रिय सेंसिंग। यह संदेश रिसीवर को यह बताने के लिए बार-बार भेजा जाता है कि एक कनेक्शन जीवित है। इस संदेश का उपयोग वैकल्पिक है। जब शुरू में प्राप्त होता है, तो रिसीवर को प्रत्येक 300ms (अधिकतम) पर एक और सक्रिय सेंसिंग संदेश प्राप्त करने की उम्मीद होगी, और यदि ऐसा नहीं होता है तो यह मान लेगा कि कनेक्शन समाप्त कर दिया गया है। समाप्ति पर, रिसीवर सभी आवाज़ों को बंद कर देगा और सामान्य (गैर-सक्रिय संवेदन) ऑपरेशन पर वापस आ जाएगा। | |
11111111 | रीसेट। सिस्टम में सभी रिसीवर को पावर-अप स्थिति में रीसेट करें। मैन्युअल नियंत्रण के तहत, इसे संयमपूर्वक उपयोग किया जाना चाहिए। विशेष रूप से, इसे पावर-अप पर नहीं भेजा जाना चाहिए। |