error reserving midi event

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

error reserving midi event

Jonatan Liljedahl
I'm trying to make a client that reads messages from my homebuilt USB
controller (serial, not midi) and writes jack midi events. I want to
send two midi cc events for each value to get 14 bit, but with the code
below I get "could not reserve midi event (course)".

If I comment out the second block (the one for fine) it works without
complaints (but then I only get 7 bits). (strange thing that it stops at
the first one instead of the second one!)

I also tried putting both events in out[] at once (using
jack_midi_event_reserve(port_buf, 0, 6)) but that didn't seem to work.
Also tried putting the fine event with timestamp 1 in case it wasn't
possible to put more than one event at the same timestamp.

I'd be very happy if anyone could help me out... here's the relevant code:

int process(jack_nframes_t nframes, void *arg)
{
  void* port_buf = jack_port_get_buffer(output_port, nframes);
  unsigned char *out, in[2];
  int data, parm;

  jack_midi_clear_buffer(port_buf);

  while(jack_ringbuffer_read_space(rb) >= 2)
  {
    jack_ringbuffer_read(rb, in, 2);
    parm = in[0] >> 2;
    data = ((in[0] << 8) | in[1]) & 0x03FF;

    out = jack_midi_event_reserve(port_buf, 0, 3);
    if(out) {
      out[2] = data >> 3; //course.
      out[1] = parm + 1;
      out[0] = 0xB0;
    } else {
      fprintf(stderr,"could not reserve midi event (course)\n");
    }

    out = jack_midi_event_reserve(port_buf, 0, 3);
    if(out) {
      out[2] = (data & 0x07) << 4; //fine.
      out[1] = parm + 33;
      out[0] = 0xB0;
    } else {
      fprintf(stderr,"could not reserve midi event (fine)\n");
    }
  }
  return 0;
}

void send_value(int parm, int val) {
  size_t wrote;
  unsigned char buf[2];
  ...
  wrote = jack_ringbuffer_write(rb, buf, 2);
  if(wrote != 2) fprintf(stderr, "event buffer overrun\n");
}

main() {
...
  output_port = jack_port_register (client, "out",
    JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
  rb = jack_ringbuffer_create(1024);
...
}

--
/Jonatan         [ http://kymatica.com ]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: error reserving midi event

Dmitry Baikov
On 10/18/07, Jonatan Liljedahl <[hidden email]> wrote:
> I'm trying to make a client that reads messages from my homebuilt USB
> controller (serial, not midi) and writes jack midi events. I want to
> send two midi cc events for each value to get 14 bit, but with the code
> below I get "could not reserve midi event (course)".
Are you getting any events at all?
If you are, then you possibly have more data than the port buffer can hold.

> I also tried putting both events in out[] at once (using
> jack_midi_event_reserve(port_buf, 0, 6)) but that didn't seem to work.
That's not right. One transaction - one MIDI message.

> Also tried putting the fine event with timestamp 1 in case it wasn't
> possible to put more than one event at the same timestamp.
It is possible.

> I'd be very happy if anyone could help me out... here's the relevant code:
The code seems to be correct.


Regards,

Dmitry.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: error reserving midi event

Jonatan Liljedahl
Dmitry Baikov wrote:
> On 10/18/07, Jonatan Liljedahl <[hidden email]> wrote:
>> I'm trying to make a client that reads messages from my homebuilt USB
>> controller (serial, not midi) and writes jack midi events. I want to
>> send two midi cc events for each value to get 14 bit, but with the code
>> below I get "could not reserve midi event (course)".
>
> Are you getting any events at all?
> If you are, then you possibly have more data than the port buffer can hold.

Yes, I get a lot of events from my controller, but it runs only at
115kbps so it's quite slow.

How big is the port buffer for jack midi events? How many bytes of midi
messages is it possible to output during one process cycle?

>> I'd be very happy if anyone could help me out... here's the relevant code:
>
> The code seems to be correct.

Strange...

--
/Jonatan         [ http://kymatica.com ]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: error reserving midi event

Dmitry Baikov
On 10/18/07, Jonatan Liljedahl <[hidden email]> wrote:
> > Are you getting any events at all?
> > If you are, then you possibly have more data than the port buffer can hold.
I meant, do you get ANY event via jack midi?

> Yes, I get a lot of events from my controller, but it runs only at
> 115kbps so it's quite slow.
So it can generate about 7200 events (2 bytes each) per second.

> How big is the port buffer for jack midi events? How many bytes of midi
> messages is it possible to output during one process cycle?
Right now MIDI buffers are of the same size as audio.
Each event have 12-byte header, so with 64 frames per buffer you can
store int(64/(12+3)) = 4 events (3 bytes each).

Taking into account you send each event as 2 CCs - 2 your full events
per buffer, one jackmidi port can hold 44100/64 * 2 -> 1378 events
from your controller per second.

It is much less than 7200. So 80% of your events are being dropped.


Dmitry.

P.S. Jackdmp implementation have a small optimisation, so events of 4
bytes or less are stored inside the header (i.e. most of events). I
can commit this to jackd anytime.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: error reserving midi event

Jonatan Liljedahl
Dmitry Baikov wrote:
> On 10/18/07, Jonatan Liljedahl <[hidden email]> wrote:
>>> Are you getting any events at all? If you are, then you possibly
>>> have more data than the port buffer can hold.
> I meant, do you get ANY event via jack midi?

This code works fine, except all the buffer fulls I get... but at least
those events are handled in the next process cycle instead of beeing
dropped:

int process(jack_nframes_t nframes, void *arg)
{
    void *port_buf = jack_port_get_buffer(output_port, nframes);
    unsigned char in[2];
    jack_midi_data_t out[3];
    int data, parm;
    int i = 0;

    jack_midi_clear_buffer(port_buf);

    out[0] = 0xB0;

    while(jack_ringbuffer_read_space(rb) >= 2)
    {
        if(jack_midi_max_event_size(port_buf) < 6) {
            fprintf(stderr,"could not reserve midi events, buffer full.\n");
            break;
        }

        jack_ringbuffer_read(rb, in, 2);
        parm = in[0] >> 2;
        data = ((in[0] << 8) | in[1]) & 0x03FF;

        out[1] = parm + 1;
        out[2] = data >> 3; //course.
        jack_midi_event_write(port_buf, i++, out, 3);

        out[1] = parm + 33;
        out[2] = (data & 0x07) << 4; //fine.
        jack_midi_event_write(port_buf, i++, out, 3);
    }

    return 0;
}

But, if I write all events with the same timestamp (0 frames) then only
the first event (course) get out to the receiving client! In the code
above I just worked around it by incrementing i. So it really seems
that it's not possible to have too many events with same timestamp. Is
this a bug?

>> Yes, I get a lot of events from my controller, but it runs only at
>> 115kbps so it's quite slow.
> So it can generate about 7200 events (2 bytes each) per second.

Since each byte in serial comm takes 10 bits it's (115200/10)/2 = 5760
events per second I think.

>> How big is the port buffer for jack midi events? How many bytes of
>> midi messages is it possible to output during one process cycle?
> Right now MIDI buffers are of the same size as audio. Each event have
> 12-byte header, so with 64 frames per buffer you can store
> int(64/(12+3)) = 4 events (3 bytes each).

Ok! This is quite a limitation. How am I supposed to send for example a
sysex message of 14 bytes? Is it possible to send half an event in one
process cycle and the other half next time? If so, it would be a
solution to stop sending bytes when jack_midi_reserve_event() returns
NULL (buffer full) and do them next time instead (even though they will
be delayed 64 frames in this case). But I guess this wouldn't work as it
would be received as multiple half-events..

> Taking into account you send each event as 2 CCs - 2 your full events
>  per buffer, one jackmidi port can hold 44100/64 * 2 -> 1378 events
> from your controller per second.
>
> It is much less than 7200. So 80% of your events are being dropped.

Too bad, that's not much faster than a hardware MIDI port, which would
be (31250/10)/3 = 1041 events per second for 3 byte events. Or 1562
events per second with running status in best cases.

Perhaps I should think about using audio streams for control signals,
but that could require some downsampling at the receiver end...

> Dmitry.
>
> P.S. Jackdmp implementation have a small optimisation, so events of 4
>  bytes or less are stored inside the header (i.e. most of events). I
> can commit this to jackd anytime.

Sounds nice! That would be great.

--
/Jonatan         [ http://kymatica.com ]


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: error reserving midi event

lars.luthman (Bugzilla)
On Thu, 2007-10-18 at 21:33 +0200, Jonatan Liljedahl wrote:

> Dmitry Baikov wrote:
> > Right now MIDI buffers are of the same size as audio. Each event have
> > 12-byte header, so with 64 frames per buffer you can store
> > int(64/(12+3)) = 4 events (3 bytes each).
>
> Ok! This is quite a limitation. How am I supposed to send for example a
> sysex message of 14 bytes? Is it possible to send half an event in one
> process cycle and the other half next time? If so, it would be a
> solution to stop sending bytes when jack_midi_reserve_event() returns
> NULL (buffer full) and do them next time instead (even though they will
> be delayed 64 frames in this case). But I guess this wouldn't work as it
> would be received as multiple half-events..
This is indeed a severe limitation and should be fixed. Ideally there
should be command line options and API functions that set 1) the minimum
MIDI buffer size and 2) the MIDI buffer size / audio buffer size ratio,
with sane defaults for both.

Is the calculation above really correct though? With 64 frames per
buffer and four bytes per frame (sizeof(float)) a buffer should be 256
bytes large, with room for 17 events.


--ll

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel

signature.asc (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: error reserving midi event

Jonatan Liljedahl
In reply to this post by Jonatan Liljedahl
Jonatan Liljedahl wrote:
> Dmitry Baikov wrote:
>> On 10/18/07, Jonatan Liljedahl <[hidden email]> wrote:
>>>> Are you getting any events at all? If you are, then you possibly
>>>> have more data than the port buffer can hold.
>> I meant, do you get ANY event via jack midi?
>
> This code works fine, except all the buffer fulls I get... but at least
> those events are handled in the next process cycle instead of beeing
> dropped:
...
>
> But, if I write all events with the same timestamp (0 frames) then only
> the first event (course) get out to the receiving client! In the code
> above I just worked around it by incrementing i. So it really seems
> that it's not possible to have too many events with same timestamp. Is
> this a bug?

Sorry, false alarm! It was a bug in my receiving client, I did
if(event.time == i) do stuff instead of while(event.time == i), so I
ignored all but the first event with the same timestamps...

But, it feels like I get more xruns (midi port buf full) if I send all
events with the same timestamp. Is this natural?

--
/Jonatan         [ http://kymatica.com ]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: error reserving midi event

Dmitry Baikov
In reply to this post by Jonatan Liljedahl
On 10/18/07, Jonatan Liljedahl <[hidden email]> wrote:
> But, if I write all events with the same timestamp (0 frames) then only
> the first event (course) get out to the receiving client!
Which version of jack do you have? SVN version does allow this.

> Since each byte in serial comm takes 10 bits it's (115200/10)/2 = 5760
> events per second I think.
You are right, of course!

> Ok! This is quite a limitation. How am I supposed to send for example a
> sysex message of 14 bytes? Is it possible to send half an event in one
> process cycle and the other half next time? If so, it would be a
> solution to stop sending bytes when jack_midi_reserve_event() returns
> NULL (buffer full) and do them next time instead (even though they will
> be delayed 64 frames in this case). But I guess this wouldn't work as it
> would be received as multiple half-events..
Yes, there is a problem with big sysex messages.
I have some ideas how to solve it, but none is good enough.
The best solution to the problem is:
allow sysex messages (and only them) to be splitted. CoreMidi API does
like this.
There are 2 problems to solve:
1) how to merge several streams and not break partial sysex
2) how to ensure that no middle part of sysex got lost.
I have an idea how to do this, but had no time until recently.
I plan to return to this problem soon.

> Too bad, that's not much faster than a hardware MIDI port, which would
> be (31250/10)/3 = 1041 events per second for 3 byte events. Or 1562
> events per second with running status in best cases.
Good point.

> Perhaps I should think about using audio streams for control signals,
> but that could require some downsampling at the receiver end...
That's a good idea.


Dmitry.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: error reserving midi event

Dmitry Baikov
In reply to this post by lars.luthman (Bugzilla)
On 10/18/07, Lars Luthman <[hidden email]> wrote:
> This is indeed a severe limitation and should be fixed. Ideally there
> should be command line options and API functions that set 1) the minimum
> MIDI buffer size and 2) the MIDI buffer size / audio buffer size ratio,
> with sane defaults for both.
Idea about minimum size added to TODO list (buffer size ratio already there).

> Is the calculation above really correct though? With 64 frames per
> buffer and four bytes per frame (sizeof(float)) a buffer should be 256
> bytes large, with room for 17 events.
That's right!


Dmitry.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel
Reply | Threaded
Open this post in threaded view
|

Re: error reserving midi event

Dmitry Baikov
In reply to this post by Jonatan Liljedahl
On 10/19/07, Jonatan Liljedahl <[hidden email]> wrote:
> But, it feels like I get more xruns (midi port buf full) if I send all
> events with the same timestamp. Is this natural?
No. It should not matter.


Dmitry.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Jackit-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jackit-devel