Re: [Jack-Devel] Dispersing MIDI messages: one to multiple

PrevNext  Index
DateFri, 30 Jan 2015 22:29:00 +0800
From Happy <[hidden] at gmail dot com>
ToMarjan Mrak <[hidden] at gmail dot com>
Cc[hidden] at lists dot jackaudio dot org
In-Reply-ToMarjan Mrak Re: [Jack-Devel] Dispersing MIDI messages: one to multiple
Follow-UpHarry van Haaren Re: [Jack-Devel] Dispersing MIDI messages: one to multiple
Consider to check for "MIDI running status"? Different devices send
running status for notes and control messages in different ways. Hook up
a MIDI monitor like GDIMonitor to see what is actually coming in.
http://www.blitter.com/~russtopia/MIDI/~jglatt/tech/midispec/run.htm

Thanks,


On 五, 2015-01-30 at 07:06 +0100, Marjan Mrak wrote:
> Thank you all.
> 
> 
> So the princple "should work". That's all I wanted to know. As far as
> I could see, there were no problems with writing messages - according
> to output.
> 
> API documentation does not provide any examples (only demo code does),
> so I was - experimenting more or less. Thus so many commented lines. I
> apologize.
> 
> 
> It's time to check jack's log, also. I've spotted messages like
> "Yoshimi client didn't finish..." in console.
> 
> 
> Cheers,
> Marjan
> 
> 
> 2015-01-29 15:19 GMT+01:00 Robin Gareus <[hidden]>:
>         Hi Marjan,
>         
>         On 01/29/2015 11:08 AM, Marjan Mrak wrote:
>         
>         [..]
>         
>         > Or is there a better way to "disperse" one MIDI message to
>         several
>         > channels?
>         
>         There are existing projects, e.g. midish, mididings,
>         qmidiroute,..
>         but your hardcoded approach is fine if it addresses your
>         issue.
>         
>         [..]
>         
>         > It works, but if I am using it, totaly at random sound
>         output
>         > "hangs" for like 10th of second.
>         
>         As Harry noted, if verb == 1, the printf() debug info could be
>         the
>         cause (blocking wait for the printed text to reach the
>         terminal).
>         Other than that there's no obvious reason, but it's a bit hard
>         to read
>         the code with all the commented out lines all and unscoped
>         variables
>         over the place.
>         
>         A few comments below inline:
>         
>         > static int process(jack_nframes_t nframes, void *arg) { int
>         res =
>         > 0; int i; int j;
>         >
>         > //unsigned char* buffer; unsigned char jbuffer[3];
>         >
>         > void* port_buf = jack_port_get_buffer(output_port, nframes);
>         >
>         > //get events void* in_port_buf =
>         jack_port_get_buffer(input_port,
>         > nframes); jack_nframes_t n =
>         > jack_midi_get_event_count(in_port_buf);
>         >
>         > jack_midi_clear_buffer(port_buf);
>         >
>         > if(n==0) return 0;
>         >
>         > jack_midi_event_t jev;
>         >
>         >
>         > if(verb == 1) printf("%i: Data arrived!\n", cnt);
>         >
>         > for(i = 0;i<n;i++){
>         >
>         > res = jack_midi_event_get(&jev,in_port_buf,i); if(res == 0){
>         > if(verb == 1){ printf("Got event, %i bytes!\n",(int)
>         jev.size);
>         > for(j=0;j<jev.size;j++) printf("%i: %i
>         \n",j,jev.buffer[j]); } }
>         > else{ if(verb == 1) printf("ERROR getting event!\n"); return
>         0; }
>         >
>         >
>         > //transmit data cnt++; //buffer =
>         jack_midi_event_reserve(port_buf,
>         > i, 3);
>         >
>         
>         check the event size
>         
>            if (jev.size != 3) {
>                continue;
>            }
>         
>         If there are one or two byte messages (eg active-sensing or
>         midi-clock) at the input, all sorts of undefined behaviour
>         could happen.
>         
>         Yet, in the code below this should be a non-issue, it always
>         check the
>         status byte first.
>         
>         >
>         > //controll to MIDI channel 1! if(jev.buffer[0] == 176 &&
>         > jev.buffer[1] == 97){ if(verb == 1) printf("MUTE CONTROL CH1
>         > sent\n"); //first button: set mute register on channel 1
>         > //buffer[0] = 176; //buffer[1] = 7; //buffer[2] =
>         jev.buffer[2];
>         > jbuffer[0] = 176;
>         
>         I'd like to suggest to use hex values for the status byte,
>         0xb0
>         instead of 176 to improve readability.
>         
>         > jbuffer[1] = 7; jbuffer[2] = jev.buffer[2]; res =
>         > jack_midi_event_write(port_buf, jev.time, jbuffer, 3); }
>         >
>         > else if(jev.buffer[0] == 176 && jev.buffer[1] ==
>         96){ if(verb ==
>         > 1) printf("MUTE CONTROL to CH2 sent\n"); //second button:
>         set mute
>         > register on channel 2 //buffer[0] = 177; //buffer[1] = 7;
>         > //buffer[2] = jev.buffer[2]; jbuffer[0] = 177; jbuffer[1] =
>         7;
>         > jbuffer[2] = jev.buffer[2]; res =
>         jack_midi_event_write(port_buf,
>         > jev.time, jbuffer, 3); }
>         >
>         > else if(jev.buffer[0] == 176 && jev.buffer[1] ==
>         66){ if(verb ==
>         > 1) printf("MUTE CONTROL CH3 sent\n"); //third button: set
>         mute
>         > register on channel 3 //buffer[0] = 176; //buffer[1] = 7;
>         > //buffer[2] = jev.buffer[2]; jbuffer[0] = 178; jbuffer[1] =
>         7;
>         > jbuffer[2] = jev.buffer[2]; res =
>         jack_midi_event_write(port_buf,
>         > jev.time, jbuffer, 3); }
>         >
>         > else if(jev.buffer[0] == 176 && jev.buffer[1] ==
>         67){ if(verb ==
>         > 1) printf("MUTE CONTROL to CH4 sent\n"); //fourth button:
>         set mute
>         > register on channel 4 //buffer[0] = 177; //buffer[1] = 7;
>         > //buffer[2] = jev.buffer[2]; jbuffer[0] = 179; jbuffer[1] =
>         7;
>         > jbuffer[2] = jev.buffer[2]; res =
>         jack_midi_event_write(port_buf,
>         > jev.time, jbuffer, 3); }
>         >
>         > else if(jev.buffer[0] == 176 && jev.buffer[1] ==
>         64){ if(verb ==
>         > 1) printf("MUTE CONTROL to CH5 sent\n"); //fifth button: set
>         mute
>         > register on channel 5 //buffer[0] = 177; //buffer[1] = 7;
>         > //buffer[2] = jev.buffer[2]; jbuffer[0] = 180; jbuffer[1] =
>         7;
>         > jbuffer[2] = jev.buffer[2]; res =
>         jack_midi_event_write(port_buf,
>         > jev.time, jbuffer, 3); }
>         >
>         > else if(jev.buffer[0] == 176 && jev.buffer[1] ==
>         65){ if(verb ==
>         > 1) printf("MUTE CONTROL to CH6 sent\n"); //sixth button: set
>         mute
>         > register on channel 6 //buffer[0] = 177; //buffer[1] = 7;
>         > //buffer[2] = jev.buffer[2]; jbuffer[0] = 181; jbuffer[1] =
>         7;
>         > jbuffer[2] = jev.buffer[2]; res =
>         jack_midi_event_write(port_buf,
>         > jev.time, jbuffer, 3); }
>         >
>         > else if(jev.buffer[0] == 176 && jev.buffer[1] == 7){ if(verb
>         == 1)
>         > printf("MUTE CONTROL to CH7 sent\n"); //seventh button: set
>         mute
>         > register on channel 7 //buffer[0] = 177; //buffer[1] = 7;
>         > //buffer[2] = jev.buffer[2]; jbuffer[0] = 182; jbuffer[1] =
>         7;
>         > jbuffer[2] = jev.buffer[2]; res =
>         jack_midi_event_write(port_buf,
>         > jev.time, jbuffer, 3); }
>         >
>         > else if(jev.buffer[0] == 176 && jev.buffer[1] ==
>         10){ if(verb ==
>         > 1) printf("MUTE CONTROL to CH8 sent\n"); //eighth button:
>         set mute
>         > register on channel 8 //buffer[0] = 177; //buffer[1] = 7;
>         > //buffer[2] = jev.buffer[2]; jbuffer[0] = 183; jbuffer[1] =
>         7;
>         > jbuffer[2] = jev.buffer[2]; res =
>         jack_midi_event_write(port_buf,
>         > jev.time, jbuffer, 3); }
>         >
>         >
>         >
>         >
>         > else if((jev.buffer[0]& 0xF0) == 128 || (jev.buffer[0]&
>         0xF0) ==
>         > 144){ //note key, pass through if(verb == 1) printf("SOUND
>         > PASSED-THROUGH\n"); //notes; let them pass //buffer[0] =
>         > jev.buffer[0]; //buffer[1] = jev.buffer[1]; //buffer[2] =
>         > jev.buffer[2]; jbuffer[0] = jev.buffer[0];  //CH1 jbuffer[1]
>         =
>         > jev.buffer[1]; jbuffer[2] = jev.buffer[2]; res =
>         > jack_midi_event_write(port_buf, jev.time , jbuffer, 3);
>         jbuffer[0]
>         > = jev.buffer[0] + 1; //CH2
>         
>         
>         These can produce invalid messages. e.g some channel 15 data
>         will
>         alter the status byte. (Note on -> Aftertouch)
>         
>         uint8_t channel = jev.buffer[0] & 0x0f;
>         uint8_t status = jev.buffer[0] & 0xf0;
>         channel = (channel + 1) & 0x0f;
>         jbuffer[0] = status | channel;
>         
>         
>         > jbuffer[1] = jev.buffer[1]; jbuffer[2] = jev.buffer[2]; res
>         =
>         > jack_midi_event_write(port_buf, jev.time , jbuffer, 3);
>         jbuffer[0]
>         > = jev.buffer[0] + 2; //CH3 jbuffer[1] = jev.buffer[1];
>         jbuffer[2] =
>         > jev.buffer[2];
>         
>         ^^ no need to re-assign, jbuffer[1], jbuffer[2]
>         
>         > res = jack_midi_event_write(port_buf, jev.time , jbuffer,
>         3);
>         > jbuffer[0] = jev.buffer[0] + 3; //CH4 jbuffer[1] =
>         jev.buffer[1];
>         > jbuffer[2] = jev.buffer[2];
>         
>         ditto.
>         
>         > res = jack_midi_event_write(port_buf, jev.time , jbuffer,
>         3); }
>         >
>         > //res = jack_midi_event_write(port_buf, i, jev.buffer,
>         3); //res =
>         > jack_midi_event_write(port_buf, jev.time, jbuffer, 3);
>         >
>         
>         Just stop if you can't write more events or a write failed.
>         
>             if (!res) {
>                 break;
>             }
>         
>         but that's just some minor optimization. It won't hurt much to
>         keep
>         calling jack_midi_event_write() again. it will just be a
>         no-op. It's
>         very unlikely to happen anyway.
>         
>         >
>         > }
>         >
>         > return 0;
>         >
>         > }
>         
>         It should work in principle, maybe there's a flaw elsewhere in
>         the
>         setup code.
>         
>         Cheers!
>         robin
> 
> 
> 
> Jack-Devel mailing list
> [hidden]
> http://lists.jackaudio.org/listinfo.cgi/jack-devel-jackaudio.org
PrevNext  Index

1422628153.15913_0.ltw:2, <1422628140.11223.8.camel at HOME3>