NOTE-Daten aus MIDI-Input isolieren
-
Hallo,
ich habe mich ein wenig an folgendem Beispiel entlanggehangelt.
https://ccrma.stanford.edu/~craig/articles/linuxmidi/alsa-1.0/alsarawmidiin.cMein Ziel ist es, die NOTE-Daten (das mittlere Byte) aus der variable buffer zu isolieren. Problem ist wohl unter Anderem, dass ich nicht zu 100% weiss was ich da eigentlch mache.
(Ehrlich währt am längsten)Um mal ein kompilierbares Beispiel zu nennen:
#include <stdio.h> #include <alsa/asoundlib.h> int main(int argc, char* argv[]) { int status, mode = SND_RAWMIDI_SYNC; snd_rawmidi_t* midiin = NULL; const char* portname = "hw:1,0,0"; unsigned char buffer[1]; if((status = snd_rawmidi_open(&midiin, NULL, portname, mode)) < 0) { printf("error opening MIDI input\n"); return 1; } while(1) { if((status = snd_rawmidi_read(midiin, buffer, 1)) < 0) { printf("error reading MIDI input\n"); return 1; } printf("%d\n", (unsigned char)buffer[0]); } snd_rawmidi_close(midiin); midiin = NULL; return 0; }
Wenn ich dies ausführe und eine Taste auf dem Midi-Keyboard drücke (und gedrückt halte, denn sonst würde ja ein weiteres MIDI-Event abgefeuert),
dann erhalte ich eine Ausgabe in dieser Form:144
48
106In diesem Fall ist die 48 der Wert, den ich gesondert abspeichern möchte.
Kann mir da jemand einen Tipp geben?Vielen Dank!
-
Wo ist da dein Problem? Jetzt antworte nicht "ich weiß nicht wie das geht"! Du sollst sagen, an welcher Stelle du warum welche Schwierigkeit damit hast. Du hast die Werte schließlich vorliegen, was hindert dich daran, mit einem davon irgendetwas zu tun?
-
So evtl?
unsigned char buffer[3]; ... while(1) { if((status = snd_rawmidi_read(midiin, buffer, 3)) < 0) { printf("error reading MIDI input\n"); return 1; } printf("%02x\n", buffer[1]); // wer braucht schon Dezimahlzahlen... ...
-
@SeppJ
Mich verwirrt vorallem diese Ausgabe. Warum erhalte ich durch ein printf-statement 3 Zeilen? Wie muss ich mir die Anordnung der einzelnen Bytes in 'buffer' da vorstellen und wie greife ich auf eines davon zu.@FurbleWurble
Ja! Danke vielmals.Also das Ganze war ein Denkfehler meinerseits, indem ich buffer viel zu klein angelegt habe um drei Byte zu speichern und so wurden die Bytes einfach nacheinander in 'buffer' geschoben. Sehe ich das richtig?
-
phf schrieb:
@SeppJ
Mich verwirrt vorallem diese Ausgabe. Warum erhalte ich durch ein printf-statement 3 Zeilen? Wie muss ich mir die Anordnung der einzelnen Bytes in 'buffer' da vorstellen und wie greife ich auf eines davon zu....
Also das Ganze war ein Denkfehler meinerseits, indem ich buffer viel zu klein angelegt habe um drei Byte zu speichern und so wurden die Bytes einfach nacheinander in 'buffer' geschoben. Sehe ich das richtig?
Nein. Du bekommst einfach schnell hintereinander 3 Werte. Ich würde von dem Link her vermuten (auch wenn die read-Funktion dort nicht beschrieben wird), dass du auch einen größeren Puffer nehmen könntest, wenn du die drei Werte gleichzeitig haben möchtest (das read wird dann höchstwahrscheinlich warten, bis drei Werte da sind).
-
phf schrieb:
Also das Ganze war ein Denkfehler meinerseits, indem ich buffer viel zu klein angelegt habe um drei Byte zu speichern und so wurden die Bytes einfach nacheinander in 'buffer' geschoben. Sehe ich das richtig?
Naja: Wieviel Du liest hängt ja nicht vom Puffer ab, sondern vom 3 Parameter von
snd_rawmidi_read()
.
Aber ich denke Du meinst das richtige.
-
Ja und doch (
) genau das meinte ich.
Edit: Okay, doch nicht so ganz, aber fast.Okay, da stand ich mächtig auf dem Schlauch. Danke nochmal.
-
Hi,
suche in Deinem Inputstream erst nach einem Byte, dessen höchstwertiges Nibbel den Wert 9 enthält. Das ist der MIDI-Event Note On.
unsigned char note, data; while( 1) { data = .... // was auch immer Du zum Lesen benutzt */ if( c>>4 == 9 ) { note = ... /* lies nächstes byte und mach was auch immer Du tun willst */ } }
Dein MIDI-Keyboard könnte ja auch andere Events schicken (Modulation, Pitch etc.). Bedenke aber, es gibt auch MIDI-Keyboards, die statt Note Off (8) wieder Note-On aber mit der Lautstärke 0 schicken, wenn die Taste losgelassen wird. Daher solltest Du evt. auch die Lautstärke prüfen. Das wäre dann das nachfolgende Byte.
unsigned char note, volume, data; while( 1) { data = .... // was auch immer Du zum Lesen benutzt */ if( c>>4 == 9 ) { note = ... /* nächstes byte ist die Note */ volume = ... /* nächstes byte ist die Lautstärke */ if( volume ) ....; } }
mfg Martin
-
Je nach Treiber und MIDI-Keyboard wird auch der sogenannte Running-Status verwendet. Details: siehe http://home.roadrunner.com/~jgglatt/tech/midispec/run.htm
D.h. wennn mehrere Tasten gedrückt werden, kann es so aussehen:
0x90 0x3C 0x70 0x40 0x71 0x43 0x72
(Das wäre beispielsweise ein C-Dur-Akkord auf Kanal Nr. 0.)
Du solltest also eine Statemachine verwenden, um die Noten-Nummern rauszufiltern.
-
Vielen Dank für die weiteren Hinweise. Das wird mir sicherlich zukünftig noch sehr nützlich sein.