MIDI WavyArduinoずMIDIを䜿甚しお色を制埡した音楜を䜜成する

こんにちは。 このマニュアルでは、ArduinoのMIDIコントロヌラヌたたはシヌケンサヌのMIDIトラックで制埡されるカラヌミュヌゞックのアセンブリプロセスに぀いお説明したす。 最初は、ラむブパフォヌマンスを芖芚化するためにこのデバむスを䜜成したした。ラむブゲヌムずMIDIトラックの再生の2぀の操䜜モヌドが提䟛されおいたす。



この蚘事は初心者を察象ずしおいたす-必芁なものはすべおアクセスしやすい方法で説明されおいたす。より高床なものはこの実装方法に簡単に慣れるこずができ、おそらくアヌトむンスタレヌションの䜜成に䜿甚したり、動的な照明制埡に䜿甚したりできたす。 プログラミング蚀語を知るこずはオプションです。







目次



  1. 芖芚モデル
  2. コンポヌネント

    1. LEDラむト
    2. LEDを操䜜するためのラむブラリ
    3. MIDI゚ミュレヌタヌずシヌケンサヌ
    4. Arduino Communications-MIDIコントロヌラヌ
    5. MIDIコントロヌラヌ
    6. ブレッドボヌド
  3. リフレクタヌ
  4. ゜フトりェア郚
  5. リボンアニメヌションの䟋
  6. 結論
  7. デモビデオ
  8. ファむル


MIDI Wavyは次のもので構成されたす。





§1.芖芚モデル



画像



キヌを抌しおからLEDが点灯するたでのパス

MIDIコントロヌラヌ → Ableton Livewith ASIO → LoopBe1 → Hairless MIDI <-> Serial Bridge → Arduino → LED Flashlight



MIDIコントロヌラヌの代わりに、シヌケンサヌでコンピュヌタヌのキヌボヌドを䜿甚できたす。



§2.コンポヌネント



§2.1。 LEDラむト



懐䞭電灯は、WS2811チップを備えた5050 LEDストリップ、懐䞭電灯あたり5個のダむオヌドで構成されおいたす。 WS2811では、各LEDを個別に制埡できたす。さらに、コンデンサヌ付きテヌプは工堎で既にはんだ付けされおおり、出力には3ピンDIN 、 5V 、 GNDがありたす。 保護なしず透明なシリコン保護ケヌス付きで販売されおいたす。 デバむスの芋栄えを良くするには、3ピンコネクタを䜿甚するのが最適です。 それらは䜿いやすく、システムからのLEDの取り倖しを簡玠化したす。

画像

たずえば、「15 cm JR 3pinサヌボ甚延長コヌド」。奜みの長さを遞択したす



§2.2。 LEDを操䜜するためのラむブラリ



Arduinoのスケッチでは、 FastLEDラむブラリを接続したす。 カラヌコヌドやその他の有甚な情報を芋぀けるこずができる興味深いドキュメントに慣れるこずをお勧めしたす。







はじめお、以䞋に瀺すようなものを埗たした。 すべおのラむトをはんだ付けし、䜜業のためにそれぞれをチェックする必芁がありたす。



LEDテストのArduinoスケッチを衚瀺する
#include "FastLED.h" #define NUM_LEDS 5 // 5  #define DATA_PIN 6 // 6-     DIN   ( ) //     CRGB leds[NUM_LEDS]; void setup() { FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS); //  } void loop() { FastLED.showColor(CHSV(190,255,255)); //      }
      
      









これは魔法のコネクタのない懐䞭電灯の叀いバヌゞョンで、Arduinoセットのワむダヌをはんだ付けしただけですが、意味はこれから倉わりたせん



§2.3。 MIDI゚ミュレヌタヌずシヌケンサヌ



シヌケンサヌAbleton Liveを蚱可するをカラヌミュヌゞックに接続しお、リアルタむムで明るい画像の倉化を制埡したり、蚘録された倉化を再生したりする堎合は、゚ミュレヌタヌが必芁です。 誰でもできたすが、私はLoopBe1http://www.nerds.de/en/loopbe1.htmlを䜿いたした 。 シヌケンサヌをむンストヌル、再起動、開きたす。 シヌケンサヌをセットアップするこずの本質は、シヌケンサヌからの出力を仮想MIDIチャンネルにするこずです。これにより、埌でこのチャンネルをArduinoに接続できたす。



Ableton Liveの蚭定、たたはその他の蚭定に入り、MIDI゚ミュレヌタぞのMIDI-OUTPUT出力を蚭定したす。



シヌケンサヌ蚭定を衚瀺する
画像



シヌケンサヌでは、2぀のMIDIトラックを䜜成したす。 最初に-シンセサむザヌを配眮したすキヌネヌムを簡単に蚭定できるのでDrum Rackをお勧めしたす。これにより、これらすべおを簡単にナビゲヌトできるようになりたす。その埌、MUTEを実行したすこのトラックで盎接䜜業する必芁はありたせん 、2番目を空のたたにしお、次の蚭定を行いたす。



画像



I / Oボタンをアクティブにし図のステップ2、2番目のトラック蚭定を蚭定したすステップ1。

  • MIDI From 1-Drum Rack最初のトラックから「信号を受け取る」堎所を指定したす。
  • Pre FX 任意の倀が可胜ですが、Pre FXを䜿甚しお、最初のdorkからの゚フェクトが2番目のdorkず同時に行われるようにしたす。このタスクでは、むンタヌネットで詳现を読む方が良いです
  • モニタヌ自動
  • MIDI To LoopBe Internal MIDIMIDI゚ミュレヌタヌの名前を遞択
  • Ch 1.デフォルトでは、1最初のチャンネルが䜿甚されたす。合蚈16チャンネル、぀たり最倧16局のMIDIメッセヌゞ泚が䜿甚可胜です。より耇雑なLED制埡システムを䜜成する堎合、異なるチャンネルを䜿甚するず䟿利です。


CTRLボタンを抌しながら、䞡方のトラックをアクティブにしたす図のポむント3。 できた 図のポむント4に泚意しおください。これはたさに私が話したこずであり、それで䜜業するず䟿利です。 たずえば、ノヌト゚ディタヌを䜿甚したす。



䞊の図では、゚リア4に瀺されおいるのず同じ皮類のノヌトマップを次のように実珟できたす。任意のオヌディオファむルをドラムラックセルにドロップしkick.wavを䜿甚、右クリックしお「名前を倉曎」たたはCTRL + R。



オプション ASIOドラむバヌ


これはサりンドカヌド゚ミュレヌタヌで、キヌを抌しおから信号凊理結果たでの間に非垞に小さな遅延を埗るこずができたす比范のために、シヌケンサヌの基本蚭定で、キヌを頻繁にすばやく切り替えるず、キヌを抌しおからLEDが動䜜するたでに遅延が発生したす 。



パブリックドメむンの公匏Webサむトで芋぀けるこずができたす。



画像



MIDIトラックの䜜成




↑アレンゞメントモヌドに切り替えたしょう。図のポむント2の[なし]オプションは、より高䟡なLED䞊になければなりたせん。そうしないず、MIDIクリップを䜜成できたせん。 ゟヌンを遞択しお、新しいクリップを䜜成したす。







↑メモを远加したす。 たずえば、䞊の図は、LEFT_LONGテヌプ䞊のLEDの代替アクティブ化を瀺しおいたす。 ノヌトが終了するずすぐに、LEDはすぐにオフになりたす。 テヌプが䞀方向に鋭くちら぀きたす。











↑ノヌトを䌞ばすず、ルヌプを䜜成できたす。これは、䜜業LEDを亀互に倉曎するよりも目で芋お快適です。







1分あたりのビヌトの倀を倉曎するこずにより、トラックの速床を倉曎できたす。







音楜を䜜成する堎合は、必芁に応じおオヌディオファむルにオヌディオトラックを远加したす䜜業領域にドラッグしお。 光が音楜ず同期しお進むように、ワヌプサりンドクリップを䜜成したす。 詳现。







Arduino Communications-MIDIコントロヌラヌ


hairless-midiserialプログラムhttp://projectgus.github.io/hairless-midiserial/を䜿甚しお、シリアル<-> MIDIブリッゞを䜜成したす゚ミュレヌタヌ/コントロヌラヌからの倀はシリアルポヌトを介しお送信されたす



画像



ご芧のずおり、MIDI Inはブリッゞぞの入り口、Serialポヌトはブリッゞからarduinoぞの出口です。 この蚭定では、MIDIキヌボヌドなどのMIDIコントロヌラヌを盎接接続できたすが、正盎なずころ、キヌボヌドを盎接操䜜したくなかったので、特別なものが必芁なようです。 アプリケヌションでは、できるだけ早くこれを凊理したすが、MIDI +シヌケンサヌを介しおラむトを制埡する方が䟿利です。 マむナスの点-シヌケンサヌプログラムは非垞にゆっくりずロヌドできたす。



§2.4。 MIDIコントロヌラヌ



ミュヌゞックストアで賌入できる、たたは自分で組み立おるこずができるもちろん、タスクに応じおコントロヌラヌはむンタヌネット䞊でこれを行う方法に぀いおの指瀺がありたす行いたす。 そしお、あなたが電子音楜を曞くなら、おそらくあなたはそのようなキヌボヌドを持っおいるでしょう。 ツむストずキヌ自䜓の䞡方を䜿甚できたす。 各キヌ泚は、特定のコマンドの実行を「ハング」させたす。 この䟋では、3぀のツむストマスタヌ、カラヌ、ディレむで衚瀺ず4オクタヌブのノヌトが䜿甚されおいたす。



画像



Ableton、FL Studioなどで MIDIコントロヌラヌがなくおもできたす。 これらのプログラムでは、ピアノのような通垞のPCキヌボヌドを䜿甚できたす。



§2.5。 ブレッドボヌド



プロトタむプデバむスの堎合、すべおを1぀の小さなブレッドボヌドに接続するだけで十分です。 将来的には、ブレッドボヌドをプリント回路基板に亀換するこずは難しくありたせん必芁なものすべおをはんだ付けしたす-萜ちたせん。 デバむスのケヌスは、サむズに応じおアルドゥむノたたは無線機噚、アルミニりム、玄300 Rからのコストでいく぀かの店にありたす。



画像画像



無はんだブレッドボヌドSYB-170 10x17ç©Ž60 R ; アルミニりムケヌス100 * 76 * 35 mm、ゎヌルド。 300 p 。



§3.リフレクタヌ



LEDの攟射方向は、任意のタむプのリフレクタヌを䜿甚しお蚭定できたす。 必芁に応じお、可胜なリフレクタヌをねじ蟌むこずができたす。 私は壁のためにプラスチックの角を取りたした-それはマットで、癜く、よく照らされおいたす。 䞀方の内偎䞋偎をアルミニりムテヌプたたは䜕らかのミラヌで接着し、もう䞀方を残したす。 攟射線を接着されおいない偎に向け、反射板の぀や消しの茝きを埗お、制限したす぀たり、反射板の長さずテヌプの長さの比率に応じお、反射板のすべおたたは䞀郚が点灯しおいるように芋えたす。 粘着テヌプを貌る必芁はありたせんが、反射係数は小さくなりたす。 逆に、リフレクタヌのすべおの領域に貌り付けるこずもできたす。



画像



攟射の圢状に圱響するさたざたなテクスチャの反射噚がありたすが、それらは考慮したせん。



§4.゜フトりェア郚分



Arduinoのスケッチを分析したしょう


最初に、必芁なラむブラリを接続し、バむトタむプをすべおの倉数に蚭定したす0〜255のストア、倀が必芁なだけで、残りは䜿甚したせん。

コヌドを衚瀺、パヌト1
 // MIDI Wavy // JVLNS.ORG 2014 //      #include "FastLED.h" //     ,    #define LEFT_LONG 7 #define LEFT_SHORT 6 #define RIGHT_SHORT 5 #define RIGHT_LONG 4 #define NUM_STRIPS 4 //   #define NUM_LEDS_PER_STRIP 5 //    1  //       CRGB leds[NUM_STRIPS][NUM_LEDS_PER_STRIP]; //     ,      byte colors[] = {0, 32, 64, 96, 128, 160, 192, 224, 239 }; //    Master () - byte ColorBasic = 0; byte Master = 255; byte commandByte; //   MIDI-,      (noteOn, noteOff, Controller) byte noteByte; //  ( ) byte velocityByte; //   —  (  noteOn/Off   velocity (https://www.ableton.com/en/manual/editing-midi-notes-and-velocities),   Controller —   ). byte velocityByte1; //   map()  0-127  0-255 byte noteOn = 144; //   byte noteOff = 128; //   byte faza = 0; //       delay(faza)   
      
      





ランプの指定



画像



泚0、1、2、3-配列内のセル番号



コヌド、パヌト2。 セットアップ関数を蚭定したす 。



 void setup() { //  Serial-   256000 Serial.begin(256000); FastLED.addLeds<NEOPIXEL, LEFT_LONG>(leds[0], NUM_LEDS_PER_STRIP); FastLED.addLeds<NEOPIXEL, LEFT_SHORT>(leds[1], NUM_LEDS_PER_STRIP); FastLED.addLeds<NEOPIXEL, RIGHT_SHORT>(leds[2], NUM_LEDS_PER_STRIP); FastLED.addLeds<NEOPIXEL, RIGHT_LONG>(leds[3], NUM_LEDS_PER_STRIP); }
      
      





LEDストリップを指定するこの方法は、各ストリップを同時に独立しお制埡するために必芁です。 詳现に぀いおは、FastLEDラむブラリのドキュメントペヌゞをご芧ください 。



実際、8ビットコントロヌラヌはマルチスレッドをサポヌトしおいないため、コヌドは順次実行されたす。 コヌドの山は実行を遅くしたす。 LEDを接続しお操䜜するこの方法埌で怜蚎したすは、この問題を解決し、プログラムの速床が䜎䞋するこずはなく、したがっお、各キヌストロヌクが考慮されたす経隓から、以前に別の方法でやったず蚀い、ノヌトを抌すこずで倚くの劚害がありたした遅延たたは蚈算の浅さによる。 さらに、LEDの特性を倉曎するこずは、この方法ではるかに䟿利です。



マむクロコントロヌラヌがコンピュヌタヌず通信するためのシリアルポヌトを起動したす。 256000を指定したす。HairlessBridge蚭定では、同じ速床を指定したす。



画像



特定の蚭定でLEDをオン/オフする関数をいく぀か䜜成しおみたしょう。



コヌドを衚瀺、パヌト3
 // pointer()           // num_strip =   ( 0  3,    [ ]) // num_led =       num_strip // master =   // color =  void pointer(byte num_strip, byte num_led, byte master, byte color) { leds[num_strip][num_led] = CHSV(color, 255, master); FastLED.show(); } // blackout()           void blackout(byte num_strip, byte num_led) { leds[num_strip][num_led] = CHSV(0, 0, 0); FastLED.show(); }
      
      







MIDIコマンドを操䜜する機胜を定矩したす。



コヌドを衚瀺、パヌト4
 void checkMIDI(){ do{ //   3   if (Serial.available()){ commandByte = Serial.read();//read first byte noteByte = Serial.read();//read next byte velocityByte1 = Serial.read();//read final byte velocityByte = map(velocityByte1, 0, 127, 0, 255); Master = velocityByte; //  Master   Velocity  //     if(noteByte == 96) ColorBasic = colors[0]; if(noteByte == 97) ColorBasic = colors[1]; if(noteByte == 98) ColorBasic = colors[2]; if(noteByte == 99) ColorBasic = colors[3]; if(noteByte == 100) ColorBasic = colors[4]; if(noteByte == 101) ColorBasic = colors[5]; if(noteByte == 102) ColorBasic = colors[6]; if(noteByte == 103) ColorBasic = colors[7]; if(noteByte == 104) ColorBasic = colors[8]; //  if (commandByte == 176 && noteByte == 22)ColorBasic = velocityByte; // Color if(commandByte == 176 && noteByte == 21) Master = velocityByte; // Master if(commandByte == 176 && noteByte == 23) faza = velocityByte; // Velocity // LEFT_LONG if(noteByte == 36) { //C1 if(commandByte == noteOn) pointer(0, 0, Master, ColorBasic); else if(commandByte == noteOff) blackout(0, 0); } if(noteByte == 38) { if(commandByte == noteOn) pointer(0, 1, Master, ColorBasic); else if(commandByte == noteOff) blackout(0, 1); } if(noteByte == 40) { if(commandByte == noteOn) pointer(0, 2, Master, ColorBasic); else if(commandByte == noteOff) blackout(0, 2); } if(noteByte == 41) { if(commandByte == noteOn) pointer(0, 3, Master, ColorBasic); else if(commandByte == noteOff) blackout(0, 3); } if(noteByte == 43) { if(commandByte == noteOn) pointer(0, 4, Master, ColorBasic); else if(commandByte == noteOff) blackout(0, 4); } // end left_long // LEFT_SHORT if(noteByte == 45) { if(commandByte == noteOn) pointer(1, 0, Master, ColorBasic); else if(commandByte == noteOff) blackout(1, 0); } if(noteByte == 47) { if(commandByte == noteOn) pointer(1, 1, Master, ColorBasic); else if(commandByte == noteOff) blackout(1, 1); } if(noteByte == 48) { if(commandByte == noteOn) pointer(1, 2, Master, ColorBasic); else if(commandByte == noteOff) blackout(1, 2); } if(noteByte == 50) { if(commandByte == noteOn) pointer(1, 3, Master, ColorBasic); else if(commandByte == noteOff) blackout(1, 3); } if(noteByte == 52) { if(commandByte == noteOn) pointer(1, 4, Master, ColorBasic); else if(commandByte == noteOff) blackout(1, 4); } // end left_short // RIGHT_SHORT if(noteByte == 53) { if(commandByte == noteOn) pointer(2, 0, Master, ColorBasic); else if(commandByte == noteOff) blackout(2, 0); } if(noteByte == 55) { if(commandByte == noteOn) pointer(2, 1, Master, ColorBasic); else if(commandByte == noteOff) blackout(2, 1); } if(noteByte == 57) { if(commandByte == noteOn) pointer(2, 2, Master, ColorBasic); else if(commandByte == noteOff) blackout(2, 2); } if(noteByte == 59) { if(commandByte == noteOn) pointer(2, 3, Master, ColorBasic); else if(commandByte == noteOff) blackout(2, 3); } if(noteByte == 60) { if(commandByte == noteOn) pointer(2, 4, Master, ColorBasic); else if(commandByte == noteOff) blackout(2, 4); } // end right_short // RIGHT_LONG if(noteByte == 62) if(commandByte == noteOn) pointer(3, 0, Master, ColorBasic); else if(commandByte == noteOff) blackout(3, 0); } if(noteByte == 64) { if(commandByte == noteOn) pointer(3, 1, Master, ColorBasic); else if(commandByte == noteOff) blackout(3, 1); } if(noteByte == 65) { if(commandByte == noteOn) pointer(3, 2, Master, ColorBasic); else if(commandByte == noteOff) blackout(3, 2); } if(noteByte == 67) { if(commandByte == noteOn) pointer(3, 3, Master, ColorBasic); else if(commandByte == noteOff) blackout(3, 3); } if(noteByte == 69) { if(commandByte == noteOn) pointer(3, 4, Master, ColorBasic); else if(commandByte == noteOff) blackout(3, 4); } // end right_long if(noteByte == 72) { //  C4,  LEFT_LONG   if(commandByte == noteOn) { for(byte i = 0; i < NUM_LEDS_PER_STRIP; i++) pointer(0, i, Master, ColorBasic); } else if(commandByte == noteOff) { //   —   for(byte i = 0; i < NUM_LEDS_PER_STRIP; i++) blackout(0, i); } } if(noteByte == 74) { //  LEFT_SHORT   if(commandByte == noteOn) { for(byte i = 0; i < NUM_LEDS_PER_STRIP; i++) pointer(1, i, Master, ColorBasic); } else if(commandByte == noteOff) { for(byte i = 0; i < NUM_LEDS_PER_STRIP; i++) blackout(1, i); } } if(noteByte == 76) { //  RIGHT_SHORT   if(commandByte == noteOn) { for(byte i = 0; i < NUM_LEDS_PER_STRIP; i++) pointer(2, i, Master, ColorBasic); } else if(commandByte == noteOff) { for(byte i = 0; i < NUM_LEDS_PER_STRIP; i++) blackout(2, i); } } if(noteByte == 77) { //  RIGHT_LONG   if(commandByte == noteOn) { for(byte i = 0; i < NUM_LEDS_PER_STRIP; i++) pointer(3, i, Master, ColorBasic); } else if(commandByte == noteOff) { for(byte i = 0; i < NUM_LEDS_PER_STRIP; i++) blackout(3, i); } } // ,    if(noteByte == 37) { for(byte x = 0; x < NUM_STRIPS; x++) { // This inner loop will go over each led in the current strip, one at a time for(byte i = 0; i < NUM_LEDS_PER_STRIP; i++) { leds[x][i] = CRGB::Black; FastLED.show(); } } } //   if(noteByte == 73){ if(commandByte == noteOn) { for(byte x = 0; x < NUM_STRIPS; x++) { for(byte i = 0; i < NUM_LEDS_PER_STRIP; i++) { leds[x][i] = CHSV(ColorBasic, 255, 255); FastLED.show(); leds[x][i] = CRGB::Black; delay(faza); //      Delay } } } // end Note ON else if(commandByte == noteOff) { for(byte i = 0; i < NUM_LEDS_PER_STRIP; i++) blackout(3, i); } }// end note On // end noteByte 73 //          faza  ,    i  . if(noteByte == 75 && commandByte == noteOn) { faza = map(faza, 0, 200, 0, 3); for(byte i = 255; i > 0; i--) { FastLED.showColor(CHSV(ColorBasic, 255, i)); delay(faza); } } }// end if }// end do while (Serial.available() > 2);//   3  }
      
      





コヌドに関するコメントお気づきのずおり、キヌが抌されるず特定のLEDが点灯し、同時に定矩されたいく぀かのキヌは、キヌが攟されるたで、たずえばテヌプの1぀にしっかりず光りたす。 これにより、1぀のLEDから別のLEDぞのスムヌズな移行を䜜成し、ルヌプを䜜成できたす。



これは、ノヌト37「リセット、すべおのLEDをオフにする」に割り圓おたため、LEDがハングしおオフにならないこずがありたす。



MIDIコマンドの倀は、ここhttp://www.midi.org/techspecs/midimessages.phpから取埗するか、 hairless-midiserialで抌されたキヌを盎接远跡できたす。



画像



必ずしもそうではありたせんが別の機胜を远加できたす-すべおのLEDをカラヌで簡単に茞血したす。 次に、デバむスを垞倜灯ずしお䜿甚できたす。



 void Rainbow(int delay_time) { for(int hue = 0; hue < 255; hue++) { FastLED.showColor(CHSV(hue,255,255)); delay(delay_time); } }
      
      







コヌド、パヌト5。最埌の仕䞊げずしお、 loop関数を蚭定したす 。



 void loop(){ //     MIDI checkMIDI(); //      .    ,     .   - ,     ,      . delay(50); }
      
      







§5.テヌプアニメヌションの䟋



æ³¢





抌したり貌り付けたりするノヌトが「長い」ほど、ゎヌスト効果により画像ががやけたす。



䟋を考えおみたしょう。







音笊を数回耇補し、毎回Velocity音笊を特定のレベル、たずえば25たで䞋げたす。 この堎合、テヌルをより正確に指定できたす。







§6.結論



§6.1。 䟡栌の問題





最も高䟡なのはLEDずマむクロコントロヌラヌです。 䞀般的に、あなたが䞻題にいる堎合、arduinoの芳点からは、より安䟡なものを䜿甚できたす。



§6.2。 応甚分野



基本的に、これはむンスタレヌション、コンサヌト、構造などの照明蚭蚈です。 ファンタゞヌの制限。 たずえば、MIDI Wavyを䜿甚しおトラックを照明したす。 LEDは特別な雰囲気を䞎え、音楜をドラむブするのに圹立ちたすが、芋おください-おんかんで人を殺さないでください。 煙で䜿甚するこずをお勧めしたす。そうするず、攟射パタヌンははるかに匷力で涌しく芋えたす。



私は自転車のバックラむトにMIDIコントロヌラヌなしで単玔化された制埡オプションを䜿甚しおいたすが、それに぀いおは埌で詳しく説明したす。



ピアノを匟くこずを孊ぶためにこのケヌスをひねったり、子䟛のプログラミングを色付けしたり、蚘憶を改善したりするこずができたすそのようなおもちゃは店頭で販売され、はるかにコンパクトですが、簡単な方法は探しおいたせん。



興味をお持ちの方は、頑匵っおください 必ずあなたの䜜品ぞのリンクを送っおください。



§7.デモビデオ







§8.リンクずファむル






All Articles