Gerätespezifische Probleme beim Empfang von MIDI-Daten mit Mikrocontroller!?

analog
analog
Registrierter Benutzer
Zuletzt hier
02.10.13
Registriert
22.07.10
Beiträge
33
Kekse
0
Ort
Odenwaldkreis
Hallo, liebe MIDI-Experten,

ich beschäftige mich seit geraumer Zeit mit der MIDI-Programmierung von Arduino-Controllern.
MIDI-Daten zu senden ist kein Problem mehr, aber das Empfangen macht mir in einigen Punkten noch ein bisschen Kopfzerbrechen.

Ich habe anfangs mit den Serial.xxx-Funktionen der Arduino-Bibliothek gearbeitet, bin dann aber auf den direkten Zugriff auf die USART-Register des mega328 umgestiegen, weil ich dachte, dass ich die Probleme damit besser in den Griff kriege. Die eingehenden Bytes führe ich zunächst einer selbstgeschriebenen Funktion zu, die die MIDI-Messages interpretiert, also das Statusbyte auswertet und die jeweilige Anzahl von zu erwartenden Datenbytes erkennt und zuweist. Diese Funktion arbeitet eigentlich schnell, so dass sie längst abgearbeitet sein müsste, bis das nächste empfangene Byte vorliegt.

Das eigentliche "Schlüsselexperiment" ist simpel: Es sollen lediglich Daten empfangen und weitergeleitet werden.

Jetzt kommt das Problem:

All das funktioniert hervorragend und ohne Einschränkungen bei folgenden MIDI-Sendern: MOOG Voyager, Korg Karma, Korg padKONTROL. Da ist auch noch genügend Zeit, irgendwelche "Kunststücke" einzubauen: Keyboard-Split, irgendwelche Manipulationen der Velocity etc. Auch die CC-Messages kommen perfekt rüber, selbst wenn man ausgiebig an den Knöpfen dreht.

Bei Roland-Gaia und Cakewalk gibt es Probleme beim Drücken zweier oder mehrerer Tasten gleichzeitig und bei den Controllern. Die Daten kommen einfach nicht vollständig rüber. All das sieht ein bisschen nach "Datenstau" aus, aber ich weiß nicht, wo der entstehen könnte. Außerdem machen die zuerst genannten Geräte ja keinerlei Probleme.

Frage also: Haben Roland-Geräte etwas gegen mich persönlich, oder liegt da ein allgemein bekannter Unterschied zwischen den Geräten vor?

Für Tipps und Anregungen bedanke ich mich schon jetzt.

Grüße von Andreas
 
Eigenschaft
 
Hi,

Ich meine, Roland benutzt gerne den "Running Status" zur Datenreduktion. Hierbei wird bei aufeinanderfolgenden gleichartigen Midi-Nachrichten nicht jedes Mal das Satus-Byte mit übertragen. Könnte das die Probleme verursachen?

Grüsse,
synthos
 
  • Gefällt mir
Reaktionen: 2 Benutzer
Danke!!! Das könnte sein!!! Wo erfahre ich mehr darüber??? Wusste bisher garnet, dass es sowas gibt!!!

---------- Post hinzugefügt um 16:09:58 ---------- Letzter Beitrag war um 12:44:20 ----------

Hallo synthos, hier vielleicht noch einige Ergänzungen zu meinen Beobachtungen:

1. Ich habe alle MIDI-Sender mit MIDI-OX unter die Lupe genommen. Da habe ich keinen Unterschied zwischen Roland- und anderen Geräten festgestellt. Akzeptiert MIDI-OX diesen "Running Status" so ohne weiteres, ohne das speziell zu vermerken? Gibt da allerdings tausend Einstellmöglichkeiten.

2. Wenn ich mit meinem Controller-Programm die MIDI-Daten weiterleite, ohne meinen "Interpreter" softwaremäßig dazwischen zu schalten, werden auch Roland/Cakewalk-Daten einwandfrei übertragen.

3. Drücke ich bei Betrieb mit meinem Interpreter, der im "Vorexperiment" einfach nur die nach Status, Data1, Data2 sortierten Bytes auf den MIDI-OUT meines Controllers weitergibt, gleichzeitig zwei Tasten, so wird mir dann von MIDI-OX nur das Note-On der EINEN, beim Loslassen nur das Note-Off der ANDEREN Taste gemeldet.

4. Probleme mit Roland/Cakewalk als Masterkeyboards gab es auch bei kommerziellen Empfängern (Dark Energy, Doepfer A-100).

5. Kann man den "Running Status"-Kram abschalten?

Danke und Grüße von Andreas
 
Hier steht ein bisschen was dazu (Abschnitt "Timing Accuracy and Running Status"). Dieser Quelle vertraue ich am ehesten in solchen Fragen.

Ich kann mir schon vorstellen, dass viele Programme und Geräte diese Art der Übertragung korrekt interpretieren. Es ist ja auch nicht schwierig zu erkennen, man muss beim Programmieren nur daran denken.

Hier mal ein kleines Beispiel, mit dem du vielleicht erkennen kannst, ob dein Interpreter alles richtig interpretieren kann/wird oder nicht.

Beispiele für zwei "gleichzeitige" Noten (der Einfachheit halber Notennummern 0 und 127, sowie Anschlag- und Loslass-Velocity 100). Alles hexadezimal, die Daten-Bytes (jeweils zwei) habe ich als Vierergruppen geschrieben, damit sie leicht von den Statusbytes zu unterscheiden sind.
  • Implementierung gemäss Spezifikation (Note-On und Note-Off haben unterschiedlichen Status): 90 0064 90 7F64 80 0064 80 7F64
  • Interpretiere "Note On" mit Velocity 0 als "Note Off": benötigt keinen Status "80" (verunmöglicht auch die Nutzung der Loslass-Velocity, was allerdings viele Keyboards sowieso nicht übertragen): 90 0064 90 7F64 90 0000 90 7F00
  • Running Status: spare drei Bytes durch Verzicht auf alle gleichen Status-Bytes nach dem ersten: 90 0064 7F64 0000 7F00
Die Reihenfolge der Notennummern kann bei gleichzeitigem Drücken/Loslassen auch vertauscht sein (serielle Übertragung!). Dein Programm sollte alle drei Datenstrings korrekt interpretieren können.

Vielleicht hilft das ein bisschen weiter. So verstehe ich das; praktische Erfahrung in der Programmierung von Midi-Software kann ich selbst nicht bieten (und in low-level programming schon gar nicht ;) [edit]Ach, das ist ja wie C bei Arduino, wusste ich gar nicht :)[/edit]).

Grüsse,
synthos
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: 2 Benutzer
Ich hab so im Gefühl, dass sich hinter Deinen Anregungen und Ideen genau die Lösung des Problems verbirgt. Muss das alles natürlich erstmal in Ruhe wirken lassen. Wenn ich dazu komme, das auszuprobieren, werde ich Dich/Euch mal auf dem Laufenden halten, ob es geklappt hat! Danke einstweilen, find ich super.

Grüße aus dem Odenwald

Andreas
 
Die MIDI Spezifikation sieht auf den ersten Blick sehr einfach aus, es stecken aber, wie du gemerkt hast, einige Tücken drin! Eine sehr gute Zusammenfassung, die ich meistens als Referenz benutze, gibt es hier.

Die Unterstützung von Running Status gehört auf jeden Fall zu einer konformen Implementierung dazu, ohne wäre es unvollständig und ungenügend. Wichtig ist auch die richtige Behandlung von System Real Time Messages. Diese können nämlich jederzeit, also auch inmitten von Sysex Messages auftreten. Das kriegen selbst viele Treiber für billige MIDI-Interfaces nicht richtig hin.

Chris
 
  • Gefällt mir
Reaktionen: 2 Benutzer
Beim Interpretieren von Low-Level-MIDI-Daten musst du jedes empfangene Byte daraufhin checken, ob das höchste Bit gesetzt ist. Wenn ja, ist es ein neues Statusbyte und gilt für alle nachfolgenden Events. Wenn nein, liegt Running Status vor und das bisherige Statusbyte gilt weiter.

Harald
 
  • Gefällt mir
Reaktionen: 4 Benutzer
Wenn man sich mit Lowlevel-MIDIprogrammierung beschäftigt, sollte man auch entsprechende Literatur dazu im Schrank haben, sonst gibts Bauchlandungen bei den Tücken. Ich empfehle das Buch "MIDI in Theorie und Praxis" aus dem Elektor-Verlag. Sehr Döpfer-lastig, was aber daran liegt, daß Herr Döpfer einer der Autoren des Buches ist. Gibts glaubich nur noch gebraucht über Amazon oder Momox/Abebooks.de etc. Dort wird auch auf die Lowlevel-Programmierung eingegangen bzw diese ist wesentlicher Bestandteil des Buches. Zum Rest wurde ja schon einiges gesagt.
Auf keinen Fall darf man System Realtime und System exklusive auseinanderreißen und Du solltest immer genug Puffer für den UART vorsehen. Die besten MIDI-Interfaces werden entweder schnell abgefragt oder haben UARTs mit FIFOs drin - an dieser Stelle hakt es nämlich oft.

Den Running Status kann man nicht abschalten, da er bei vielen Geräten standardmäßig drin ist. Eine gute Interfaceroutine muß damlt umgehen können. Der Running Status wurde eingeführt, um zu sendende Bytes zu sparen und somit Pufferüberlauf bzw damalige MCU-Kapazitäten nicht zusehr auszureizen.
 
Beim Interpretieren von Low-Level-MIDI-Daten musst du jedes empfangene Byte daraufhin checken, ob das höchste Bit gesetzt ist. Wenn ja, ist es ein neues Statusbyte und gilt für alle nachfolgenden Events. Wenn nein, liegt Running Status vor und das bisherige Statusbyte gilt weiter.


Das ist m.E. unzulässig vereinfacht. Für System Real Time Messages gilt dies eben nicht, da diese, wie gesagt, auch in mitten z.B. einer System Exclusive Nachricht kommen können (auch wenn das schlechte Praxis ist, lässt es sich nicht immer vermeiden). Danach wird kein neues Status Byte gesendet und es gilt kein Running Status.

Für Detailfragen geeignete Literatur heranziehen und daran denken, den Code mit allem möglichen validen und invaliden Input zu testen.
 
Zuletzt bearbeitet:
Danke an strogon14, HaraldS und microbug für die Tipps. Habe den Link gleich mal meiner Linkliste einverleibt. Bemühe mich gerade um das Einbauen des "Running Status". Der nächste Schritt wird dann die korrekte Behandlung der SysEx-Messages sein, eins nach dem anderen eben. Wie ist das mit dem Running Status eigenlich bei Control Changes? Wenn ich ausgiebig an einem Controller drehe, würde es ja ausreichen, wenn nur das zweite Datenbyte wiederholt wird?! Oder wird nur auf das CC-Statusbyte verzichtet, dann aber die Controller-Nr. und der Wert gesendet?

Grüße von Andreas
 
Zuletzt bearbeitet:
Hallo, all Ihr hilfsbereiten Ratgeber,

hab zwar derzeit gar nicht genügend Zeit zum Experimentieren, aber nach so vielen Antworten auf meine Anfrage hin hab ich mich doch jetzt ein bisschen unter Druck (den brauch manch einer eben :)) gefühlt und das ganze mal ausprobiert. Im C++ Programmcode waren es dann tatsächlich nur zwei Zeilen, die die Sache zum Laufen brachten. Es lag wirklich am (noch nicht berücksichtigten) Runnig Status, freu!!! Allerdings ist das Programm (genauer gesagt: die Funktionen der Klasse, deren Objekte als meine MIDI-Empfänger fungieren) noch net so besonders elegant, muss noch ein bisschen dran herumfeilen und vor allem auch noch die Sache mit den SysEx samt evtl. dazwischen gesendeter Real Time Messages in den Griff kriegen. Hab den Code übrigens in einer Klasse implementiert, damit ich zum Beispiel mit den 4 USARTS des AVRmega2560 gleich 4 unabhängige MIDI-IN bedienen kann ...

Jedenfalls ist das schon mal ein schöner Teilerfolg für mich als MIDI-Anfänger: Immerhin kann ich mit den Roland/Cakewalk-Geräten jetzt auch Empfänger ansteuern, die den Running Status nicht kennen, denn der Controller hat ausgangseitig derzeit keinen Running Status; das solll sich noch ändern, so dass ich das per Schalter oder sonstwie einstellen kann. Klar, dass es bei intensivem Input sonst zu einem Buffer-Overflow kommen kann.

Also: D A N K E an Euch alle! :great:

Grüße von Andreas
 
Hallo Analog, Hallo Synthos

Zum Running Status unter Windows (weil analysiert mid MIDi-OX) ist noch Folgendes anzumerken. Jedes mir bekannrte MIDI Interface incl. Treiber erweitert eine via Running Status (3 byte + n*2 byte) message auf einzelne 3 byte messages (1 Status byte + 2 daten bytes), das passt zumindest bei USB MIDI s. http://www.usb.org/developers/devclass_docs nämlich wunderbar in ein 32-bit Wort. MIDI-OX kann deshalb gar nichts anderes als vollständige MIDI msgs erkennen. Darauf bin ich anfangs auch reingefallen.
analog, bau doch mit deinem Arduno einen echten MIDI Monitor der die echten empfangenen Daten als Ascii-Zeichen via RS232 COM-IF mit z.B. 38k4 baud an ein hundskommunes Terminal Programm (wie HyperTerm v. Windows) weiterleitet. Dann siehst du, was tatsächlich aus einem Roland Keyboard herraus kommt. Da gibt es u.U. noch andere "Nettigkeiten" wie All Notes Off nach dem Loslassen aller Tasten u. ä. Viel Spaß damit (ernst gemeint) !

Gruß
Jo
 
  • Gefällt mir
Reaktionen: 2 Benutzer
Hallo nlate,

danke für den Tipp. Werde versuchen, ihn in den Sommerferien gleich mal umzusetzen. Werde dann auch erste Experimente mit dem Arduina Mega machen: Da hab ich dann 4 USARTs. Wenn ich mit einer USART den PC ansteuere, bleiben mir noch drei USARTs für MIDI, heißt drei unabhängige MIDI-IN und MIDI-OUT, ächz. Mir wird schon ein bisschen schwindelig bei dem Gedanken, was ich damit alles anstellen (und wie ich mich dabei hoffnungslos verzetteln) könnte :gruebel:. Will dann unter anderem mal einen Merger programmieren, mit dessen Hilfe ich zum Beispiel mit zwei verschiedenen Keyboards mein Nord Rack 2X ansteuern kann. Klar kann man das auch einfacher haben, aber ich muss versuchen, mich langsam an die volle Bandbreite meiner teilweise etwas verrückten Ideen heranzutasten, damit ich den Überblick net ganz verliere.

Schönes WE und Grüße von Andreas
 

Ähnliche Themen


Unser weiteres Online-Angebot:
Bassic.de · Deejayforum.de · Sequencer.de · Clavio.de · Guitarworld.de · Recording.de

Musiker-Board Logo
Zurück
Oben