MIDI In

In diesem Abschnitt werden wir lernen, wie man einen MIDI Controller verbindet, sodass er Ereignisse an Sonic Pi sendet, um unsere Synths und Töne zu kontrollieren. Nimm dir einen MIDI Controller, wie beispielsweise ein Keyboard oder eine Control Oberfläche und lass uns loslegen!

Verbinde einen MIDI Controller

Um Informationen von einem externen MIDI Gerät in Sonic Pi zu bekommen müssen wir es erst an unseren Computer anschließen. Normalerweise wird das mit einer USB Verbindung passieren, aber ältere Geräte haben einen 5-Pin DIN Stecker für den du Hardwareunterstützung in deinem Computer brauchst(manche Soundkarten haben zum Beispiel MIDI DIN Stecker). Nachdem du dein Gerät angeschlossen hast, starte Sonic Pi und wirf einen Blick auf den EA Abschnitt in den Einstellungen. Du solltest dein Gerät dort aufgelistet sehen. Wenn nicht, drücke den “Reset MIDI” button und schaue ob es auftaucht. Wenn du immer noch nichts siehst ist der nächste Schritt zu versuchen in der MIDI Konfiguration deines Betriebssystems nachzusehen um zu sehen ob sie dein Gerät erkennt. Wenn das fehlschlägt, kannst du gerne im öffentlichen Chat Fragen stellen: http://gitter.im/samaaron/sonic-pi

Erhalte MIDI Ereignisse

Nachdem dein Gerät verbunden ist, empfängt Sonic Pi automatisch Events. Du kannst das selbst nachprüfen indem du dein MIDI Gerät bedienst und auf den Cue Logger unten rechts im Anwendungsfenster unterhalb des Logs schaust (wenn das nicht sichtbar ist gehe zu Einstellungen->Editor->Ein-/Ausblenden und aktiviere die ‘Zeige cue Log’ checkbox). Du wirst einen Datenstrom an Events sehen wie:

/midi:nanokey2_keyboard:0:1/note_off  [55, 64]
/midi:nanokey2_keyboard:0:1/note_on   [53, 102]
/midi:nanokey2_keyboard:0:1/note_off  [57, 64]
/midi:nanokey2_keyboard:0:1/note_off  [53, 64]
/midi:nanokey2_keyboard:0:1/note_on   [57, 87]
/midi:nanokey2_keyboard:0:1/note_on   [55, 81]
/midi:nanokey2_keyboard:0:1/note_on   [53, 96]
/midi:nanokey2_keyboard:0:1/note_off  [55, 64]

Wenn du einen Datenstrom an Nachrichten wie diesen sehen kannst, hast du dein MIDI Gerät erfolgreich verbunden. Glückwunsch, lass uns schauen, was wir damit machen können!

MIDI Time State

Diese Events sind in zwei Abschnitte unterteilt. Erstens gibt es den Namen des Events, wie /midi:nanokey2_keyboard:0:1/note_on und zweitens gibt es die Werte des Events wie [18, 62]. Interessanter Weise sind das die zwei Dinge, die wir brauchen, um Informationen in Time State zu speichern. Sonic Pi fügt eingegangene MIDI Events automatisch in Time State ein. Das bedeutet du kannst auf den neuesten MIDI Wert mit get zugreifen und auch mit sync auf den nächsten MIDI Wert warten indem du alles was du in Abschnitt 10 dieses Tutorials gelernt hast nutzt.

Effekte steuern

Jetzt nachdem wir ein MIDI Gerät verbunden, seine Events im cue Log gesehen und entdeckt haben, dass unser Wissen über Time State alles ist, was wir zum Arbeiten mit Events brauchen, können wir anfangen Spaß zu haben. Lass uns ein einfaches MIDI Klavier bauen:

live_loop :midi_piano do
  note, velocity = sync "/midi:nanokey2_keyboard:0:1/note_on"
  synth :piano, note: note
end

Es passieren einige Dinge im obigen Code, auch einiges Problematisches. Zuerst haben wir einfach einen live_loop, der für immer den Code zwischen dem do/end Block wiederholt. Das wurde in Abschnitt 9.2 eingeführt. Danach rufen wir sync auf, um auf das nächste Time State Event zu warten. Wir benutzen einen String, der die MIDI Nachricht repräsentiert, nach der wir suchen (welcher der selbe ist, wie der, der im cue Logger angezeigt wurde). Bemerke, dass dieser lange String von Sonic Pis Autovervollständigung vervollständigt wird, sodass du ihn nicht komplett von Hand eintippen musst. Im Log haben wir gesehen, dass es zwei Werte für jedes MIDI “note on” Event gibt, also weisen wir das Ergebnis an zwei separate Variablen note und velocity zu. Schlussendlich lösen wir den :piano Synth aus und übergeben unsere Note.

Jetzt probiere du es. Gib den obigen Code ein und ersetzte den sync Schlüssel mit einer Zeichenkette die deinem spezifischen MIDI Gerät entspricht und drücke Ausführen. Hey presto, du hast ein funktionierendes Klavier! Du bemerkt jedoch wahrscheinlich ein paar Probleme: Erstens sind alle Noten gleich laut, unabhängig davon, wie stark du das Klavier anschlägst. Das kann einfach behoben werden indem wir den velocity MIDI Wert nutzen und in eine Amplitude umwandeln. Nachdem MIDI einen Wertebereich von 0-127 hat müssen wir, um diese Zahl in einen Wert zwischen 0->1 zu konvertieren, nur durch 127 teilen:

live_loop :midi_piano do
  note, velocity = sync "/midi:nanokey2_keyboard:0:1/note_on"
  synth :piano, note: note, amp: velocity / 127.0
end

Aktualisiere den Code und drücke erneut auf Ausführen. Jetzt wird der Anschlag des Klaviers berücksichtigt. Als nächstes lass uns diese ärgerliche Pause loswerden.

Latenz entfernen

Bevor wir die Pause entfernen können, müssen wir erfahren, warum sie da ist. Um alle Synths und FX auf einer Vielzahl an verschiedenen unterschiedlich starken CPUs gut getaktet zu halten, setzt Sonic Pi das Audio standardmäßig 0,5s im voraus an. (Beachte, dass diese zusätzliche Latenz über die fns set_sched_ahead_time! und use_sched_ahead_time konfiguriert werden kann). Diese 0,5s Latenz wird zu unseren :piano Synth Auslösern hinzugefügt, wie es bei allen Synths, die von Sonic Pi ausgelöst werden, passiert. Normalerweise möchten wir diese Latenz wirklich, weil sie bedeutet, dass alle Synths gut getaktet werden. Das ergibt jedoch nur Sinn bei Synths, die von Code durch play und sleep ausgelöst werden. In diesem Fall lösen wir den :piano Synth mit unserem externen MIDI Gerät aus und möchten daher nicht, dass Sonic Pi das Timing für uns kontrolliert. Wir können diese Latenz mit dem Befehl use_real_time ausschalten, welches die Latenz für den aktuellen Thread abschaltet. Das bedeutet, dass du den Echtzeitmodus für Live-Loops benutzen kannst, die ihr Timing durch syncen mit externen Geräten kontrollieren, und die normale Latenz für alle anderen Live-Loops behalten kannst. Schauen wir mal:

live_loop :midi_piano do
  use_real_time
  note, velocity = sync "/midi:nanokey2_keyboard:0:1/note_on"
  synth :piano, note: note, amp: velocity / 127.0
end

Passe deinen Code an, sodass er dem obigen Code entspricht und drücke erneut auf Ausführen. Jetzt haben wir ein Klavier mit niedriger Latenz und variablem Anschlag in nur 5 Zeilen programmiert. War das nicht einfach!

Werte erhalten

Schließlich, nachdem unsere MIDI Events direkt in den Time State gehen, können wir die get fn benutzen um den letzten gesehenen Wert zu erhalten. Das blockiert nicht den aktuellen Thread und gibt nil zurück, wenn es keinen Wert gibt (was du überschreiben kannst, indem du einen Standardwert übergibst - schaue in die Dokumentation für get). Erinnere dich, dass du get in jedem Thread zu jeder Zeit aufrufen kannst, um den letzten zutreffenden Time State Wert zu sehen. Du kannst sogar time_warp benutzen um in der Zeit zurück zu reisen und get aufrufen um vergangene Events zu sehen…

Du hast jetzt die Kontrolle

Das spannende ist jetzt, dass du jetzt die gleichen Code Strukturen benutzen kannst um MIDI Informationen von irgendeinem MIDI Gerät zu syncen und geten und mit den Werten tun kannst was auch immer du möchtest. Du kannst jetzt entscheiden was dein MIDI Gerät tun wird!