Csound Csound-dev Csound-tekno Search About

[Csnd] MIDI buffer reading

Date2010-06-07 03:22
FromJim Aikin
Subject[Csnd] MIDI buffer reading
I'm using QuteCsound 0.5 and Csound 5.11 under Windows 7. I'm attempting to
use Csound for real-time MIDI event processing, but what I'm finding in my
preliminary tests is that the midiin opcode is not buffering and releasing
the messages in the way that I would expect or hope that it would.

I'm getting stuck notes. Lots of them.

What I would expect or hope would be that on each k-cycle, midiin would
divest itself of one complete MIDI message. But I'm getting extra note-ons
when I play chords. Perhaps someone can suggest a workaround (other than,
"Use Max for this").

For starters, here's the .csd I'm using:






sr = 88200
ksmps = 1
nchnls = 1 

instr 101
kstatus init 0

kstatus, kchan, kdata1, kdata2 midiin

if (kstatus == 144) then
	printks "kstatus= %d, kchan = %d, note# = %d, velocity = %d\\n", 0,
kstatus, kchan, kdata1, kdata2 
	midiout	kstatus, kchan, kdata1, kdata2
endif

endin



i 101 0 60
e



As long as I play single, separated notes on the keyboard, this works fine.
But chords cause midiin to freak out. Here's the output when I run this.
First I'm playing C-E-G as individual notes, and then I play C-E-G as a
chord, starting all three notes at more or less the same time:

SECTION 1:
new alloc for instr 101:
  rtevent:	   T  1.556 TT  1.556 M:      0.0
new alloc for instr 101:
kstatus= 144, kchan = 1, note# = 60, velocity = 52
  rtevent:	   T  1.860 TT  1.860 M:      0.0
kstatus= 144, kchan = 1, note# = 60, velocity = 0
  rtevent:	   T  2.229 TT  2.229 M:      0.0
kstatus= 144, kchan = 1, note# = 64, velocity = 62
  rtevent:	   T  2.564 TT  2.564 M:      0.0
kstatus= 144, kchan = 1, note# = 64, velocity = 0
  rtevent:	   T  2.924 TT  2.924 M:      0.0
kstatus= 144, kchan = 1, note# = 67, velocity = 62
  rtevent:	   T  3.241 TT  3.241 M:      0.0
kstatus= 144, kchan = 1, note# = 67, velocity = 0
  rtevent:	   T  4.574 TT  4.574 M:      0.0
  rtevent:	   T  4.574 TT  4.574 M:      0.0
new alloc for instr 101:
  rtevent:	   T  4.574 TT  4.574 M:      0.0
new alloc for instr 101:
kstatus= 144, kchan = 1, note# = 60, velocity = 56
kstatus= 144, kchan = 1, note# = 64, velocity = 56
kstatus= 144, kchan = 1, note# = 67, velocity = 54
kstatus= 144, kchan = 1, note# = 64, velocity = 56
kstatus= 144, kchan = 1, note# = 67, velocity = 54
kstatus= 144, kchan = 1, note# = 67, velocity = 54
  rtevent:	   T  5.016 TT  5.016 M:      0.0
kstatus= 144, kchan = 1, note# = 64, velocity = 0
kstatus= 144, kchan = 1, note# = 60, velocity = 0
kstatus= 144, kchan = 1, note# = 67, velocity = 0
inactive allocs returned to freespace
end of score.		   overall amps:      0.0

As you can see, when I play the three-note chord, note 64 is triggered twice
and note 67 three times. Yet when I lift my fingers (the Yamaha keyboard is
presumably transmitting note-offs as note-ons with velocity of 0), the notes
are only stopped once.

This could be a problem with how midiin interprets running status (though I
don't know that the Yamaha is using running status -- that's just a guess),
or it could just be a side effect of how midiin deals with stuff that's in
its buffer.

Is there any way for me to work around this problem? Thanks for any
suggestions!

--Jim Aikin

P.S.: I'm testing this by getting an input from an M-Audio Firewire 410's
MIDI driver and outputting to MIDI Yoke 1. Cubase is then using MIDI Yoke 1
as its MIDI input. This should not be a source of problems, I'm just
documenting it here to be thorough.

Date2010-06-07 04:18
FromMichael Gogins
Subject[Csnd] Re: MIDI buffer reading
I have not used the midiin opode, but if I had, I would expect it to
be called in a loop until kstatus is zero. That would enable any
number of pending messages to be pulled from the buffer. This would be
in keeping with the MIDI protocol, whereas having only one MIDI
message per kperiod would not be sufficient to handle the protocol,
which supports multiple simultaneous messages.

When I examine the source code for midiin, that is indeed what it
appears to be doing.

So, I suggest you set up a loop in your instrument and read MIDI
events using midiin until midiin returns a status of 0, something like
this:

kstatus init 0
top_of_loop:
kstatus, kchan, kdata1, kdata2 midiin
if (kstatus == 144) then
       printks "kstatus= %d, kchan = %d, note# = %d, velocity = %d\\n", 0,
kstatus, kchan, kdata1, kdata2
       midiout kstatus, kchan, kdata1, kdata2
endif
if kstatus != 0 kgoto top_of_loop

No guarantee that this works, but let us know if it does!

Hope this helps,
Mike

On Sun, Jun 6, 2010 at 10:22 PM, Jim Aikin  wrote:
>
> I'm using QuteCsound 0.5 and Csound 5.11 under Windows 7. I'm attempting to
> use Csound for real-time MIDI event processing, but what I'm finding in my
> preliminary tests is that the midiin opcode is not buffering and releasing
> the messages in the way that I would expect or hope that it would.
>
> I'm getting stuck notes. Lots of them.
>
> What I would expect or hope would be that on each k-cycle, midiin would
> divest itself of one complete MIDI message. But I'm getting extra note-ons
> when I play chords. Perhaps someone can suggest a workaround (other than,
> "Use Max for this").
>
> For starters, here's the .csd I'm using:
>
> 
> 
> 
> 
>
> sr = 88200
> ksmps = 1
> nchnls = 1
>
> instr 101
> kstatus init 0
>
> kstatus, kchan, kdata1, kdata2 midiin
>
> if (kstatus == 144) then
>        printks "kstatus= %d, kchan = %d, note# = %d, velocity = %d\\n", 0,
> kstatus, kchan, kdata1, kdata2
>        midiout kstatus, kchan, kdata1, kdata2
> endif
>
> endin
>
> 
> 
> i 101 0 60
> e
> 
> 
>
> As long as I play single, separated notes on the keyboard, this works fine.
> But chords cause midiin to freak out. Here's the output when I run this.
> First I'm playing C-E-G as individual notes, and then I play C-E-G as a
> chord, starting all three notes at more or less the same time:
>
> SECTION 1:
> new alloc for instr 101:
>  rtevent:         T  1.556 TT  1.556 M:      0.0
> new alloc for instr 101:
> kstatus= 144, kchan = 1, note# = 60, velocity = 52
>  rtevent:         T  1.860 TT  1.860 M:      0.0
> kstatus= 144, kchan = 1, note# = 60, velocity = 0
>  rtevent:         T  2.229 TT  2.229 M:      0.0
> kstatus= 144, kchan = 1, note# = 64, velocity = 62
>  rtevent:         T  2.564 TT  2.564 M:      0.0
> kstatus= 144, kchan = 1, note# = 64, velocity = 0
>  rtevent:         T  2.924 TT  2.924 M:      0.0
> kstatus= 144, kchan = 1, note# = 67, velocity = 62
>  rtevent:         T  3.241 TT  3.241 M:      0.0
> kstatus= 144, kchan = 1, note# = 67, velocity = 0
>  rtevent:         T  4.574 TT  4.574 M:      0.0
>  rtevent:         T  4.574 TT  4.574 M:      0.0
> new alloc for instr 101:
>  rtevent:         T  4.574 TT  4.574 M:      0.0
> new alloc for instr 101:
> kstatus= 144, kchan = 1, note# = 60, velocity = 56
> kstatus= 144, kchan = 1, note# = 64, velocity = 56
> kstatus= 144, kchan = 1, note# = 67, velocity = 54
> kstatus= 144, kchan = 1, note# = 64, velocity = 56
> kstatus= 144, kchan = 1, note# = 67, velocity = 54
> kstatus= 144, kchan = 1, note# = 67, velocity = 54
>  rtevent:         T  5.016 TT  5.016 M:      0.0
> kstatus= 144, kchan = 1, note# = 64, velocity = 0
> kstatus= 144, kchan = 1, note# = 60, velocity = 0
> kstatus= 144, kchan = 1, note# = 67, velocity = 0
> inactive allocs returned to freespace
> end of score.              overall amps:      0.0
>
> As you can see, when I play the three-note chord, note 64 is triggered twice
> and note 67 three times. Yet when I lift my fingers (the Yamaha keyboard is
> presumably transmitting note-offs as note-ons with velocity of 0), the notes
> are only stopped once.
>
> This could be a problem with how midiin interprets running status (though I
> don't know that the Yamaha is using running status -- that's just a guess),
> or it could just be a side effect of how midiin deals with stuff that's in
> its buffer.
>
> Is there any way for me to work around this problem? Thanks for any
> suggestions!
>
> --Jim Aikin
>
> P.S.: I'm testing this by getting an input from an M-Audio Firewire 410's
> MIDI driver and outputting to MIDI Yoke 1. Cubase is then using MIDI Yoke 1
> as its MIDI input. This should not be a source of problems, I'm just
> documenting it here to be thorough.
> --
> View this message in context: http://old.nabble.com/MIDI-buffer-reading-tp28800403p28800403.html
> Sent from the Csound - General mailing list archive at Nabble.com.
>
>
>
> Send bugs reports to the Sourceforge bug tracker
>            https://sourceforge.net/tracker/?group_id=81968&atid=564599
> Discussions of bugs and features can be posted here
> To unsubscribe, send email sympa@lists.bath.ac.uk with body "unsubscribe csound"
>
>



-- 
Michael Gogins
Irreducible Productions
http://www.michael-gogins.com
Michael dot Gogins at gmail dot com


Send bugs reports to the Sourceforge bug tracker
            https://sourceforge.net/tracker/?group_id=81968&atid=564599
Discussions of bugs and features can be posted here
To unsubscribe, send email sympa@lists.bath.ac.uk with body "unsubscribe csound"


Date2010-06-07 05:02
FromJim Aikin
Subject[Csnd] Re: MIDI buffer reading
Michael Gogins-2 wrote:
> 
> I have not used the midiin opode, but if I had, I would expect it to
> be called in a loop until kstatus is zero. That would enable any
> number of pending messages to be pulled from the buffer. This would be
> in keeping with the MIDI protocol, whereas having only one MIDI
> message per kperiod would not be sufficient to handle the protocol,
> which supports multiple simultaneous messages.
> 

There are several things about what you're saying that I don't quite
understand. First, MIDI doesn't support multiple simultaneous messages --
it's a serial protocol. Second, I deliberately set sr = 88200 and ksmps = 1
so that the k-cycle loop would be much faster than the 1ms required for a
single MIDI message to arrive at the input buffer. Third, if midiin can, as
you say, pull a number of pending messages from the buffer, where is it
going to put the data? The outputs of this opcode are not arrays, they're
single k-rate variables. Fourth, the k-rate cycle _is_ a loop. It's not
clear to me that your suggested code changes the execution of the statments
in the instrument at all.


Michael Gogins-2 wrote:
> 
> When I examine the source code for midiin, that is indeed what it
> appears to be doing.
> 

To me (and I haven't looked at the source code, nor would I necessarily be
able to understand it if I did), this statement only illustrates my question
from a different angle. How can it pull multiple messages from the buffer
when there's only going to be one message in the buffer at any given time?
There can only be multiple messages in the buffer if midiin is failing to
empty the buffer after reading a message.

In any event, I did try your implementation of a loop. Assuming I did the
code properly, and I think I did, it made no difference. I still get stuck
notes.

Here's something that I think is suggestive (possibly): When I inspect my
latest run, the chord input (playing 3 notes together) looks like this:

  rtevent:	   T  4.927 TT  4.927 M:      0.0
kstatus= 144, kchan = 1, note# = 67, velocity = 56
  rtevent:	   T  4.939 TT  4.939 M:      0.0
new alloc for instr 101:
kstatus= 144, kchan = 1, note# = 64, velocity = 57
kstatus= 144, kchan = 1, note# = 64, velocity = 57
  rtevent:	   T  4.942 TT  4.942 M:      0.0
new alloc for instr 101:
kstatus= 144, kchan = 1, note# = 60, velocity = 42
kstatus= 144, kchan = 1, note# = 60, velocity = 42
kstatus= 144, kchan = 1, note# = 60, velocity = 42
  rtevent:	   T  5.290 TT  5.290 M:      0.0
kstatus= 144, kchan = 1, note# = 64, velocity = 0
kstatus= 144, kchan = 1, note# = 64, velocity = 0
kstatus= 144, kchan = 1, note# = 64, velocity = 0
  rtevent:	   T  5.292 TT  5.292 M:      0.0
kstatus= 144, kchan = 1, note# = 67, velocity = 0
kstatus= 144, kchan = 1, note# = 67, velocity = 0
  rtevent:	   T  5.294 TT  5.294 M:      0.0
kstatus= 144, kchan = 1, note# = 60, velocity = 0
inactive allocs returned to freespace

You'll note that the first key-down event happens once, the second happens
twice, and the third happens three times. When I lift my fingers, the same
thing happens in reverse: The first note-off (note-on, vel 0) happens three
times, the second twice, and the third only once. Because I failed to lift
the keys in the opposite order from the order in which I played them, the
number of note-offs is wrong.

Indeed, as I retest, this appears to be entirely consistent behavior, even
if I separate the note-ons and note-offs by a rather considerable space of
time. So it isn't a problem with data getting crowded together in the buffer
owing to the MIDI messages being too close together. It's a problem with how
midiin is processing the buffer.

It's a bug, and a serious one. Check me out on this ... I'm using the Ouija
board here ... but it appears that even though midiin has removed the data
for the first note-on from the buffer, it hasn't updated a counter properly
to indicate that that data is gone. So when the second note-on arrives, the
opcode outputs the new note twice, because it's consulting the counter when
it shouldn't. The fact that this happens in reverse in response to note-offs
strongly suggests that midiin is attempting to count how many note-ons have
been received that don't yet correspond to note-offs. It's attempting to do
something intelligent with hanging notes (though there is no output from the
opcode that would correspond to a note counter). It is then outputting later
events multiple times, based on its counter value for the number of
currently sounding notes.

Am I anywhere close to getting it right?

--JA



Date2010-06-07 07:17
Fromdp51
Subject[Csnd] Re: MIDI buffer reading
Hi,

I think you're problem is that MIDI is creating extra instances of instr
101.
Try adding this to your orc:

massign 0, 0

to disable MIDI mapping to instruments.

Davis

Date2010-06-07 07:30
FromJim Aikin
Subject[Csnd] Re: MIDI buffer reading
Give that man a kewpie doll!!! You're right, Davis. That solved the problem.
Copious thanks.

As Sherlock Holmes once remarked, it's obvious once it's explained to
you....

--Jim Aikin


dp51 wrote:
> 
> Hi,
> 
> I think you're problem is that MIDI is creating extra instances of instr
> 101.
> Try adding this to your orc:
> 
> massign 0, 0
> 
> to disable MIDI mapping to instruments.
> 
> Davis
> 
> 

Date2010-06-07 08:28
Fromdp51
Subject[Csnd] Re: MIDI buffer reading
Glad I could help!  But, I'm afraid I have to decline your gift.  Those
things look scary...

Davis


Jim Aikin wrote:
> 
> Give that man a kewpie doll!!! You're right, Davis. That solved the
> problem. Copious thanks.
> 
> As Sherlock Holmes once remarked, it's obvious once it's explained to
> you....
> 
> --Jim Aikin
> 
> 
> 

Date2010-06-07 12:21
FromMichael Gogins
Subject[Csnd] Re: Re: MIDI buffer reading
You are right that MIDI is a serial protocol, you are wrong that it
does not support multiple simultaneous events, that happens in MIDI
files where numerous events can have the same timestamp.

There is a loop in my code, but if you are running at 1 ms latency it
would not usually behave differently than without the loop. The data
is going into scalar variables that are being reassigned, obviously,
but not before they have done their job in providing an output.

Dave obviously identified your real problem, but if you were running
with higher latency you would have had another problem that my
proposal would probably have solved.

Regards,
Mike

On Mon, Jun 7, 2010 at 3:28 AM, dp51  wrote:
>
> Glad I could help!  But, I'm afraid I have to decline your gift.  Those
> things look scary...
>
> Davis
>
>
> Jim Aikin wrote:
>>
>> Give that man a kewpie doll!!! You're right, Davis. That solved the
>> problem. Copious thanks.
>>
>> As Sherlock Holmes once remarked, it's obvious once it's explained to
>> you....
>>
>> --Jim Aikin
>>
>>
>>
>
> --
> View this message in context: http://old.nabble.com/MIDI-buffer-reading-tp28800403p28801848.html
> Sent from the Csound - General mailing list archive at Nabble.com.
>
>
>
> Send bugs reports to the Sourceforge bug tracker
>            https://sourceforge.net/tracker/?group_id=81968&atid=564599
> Discussions of bugs and features can be posted here
> To unsubscribe, send email sympa@lists.bath.ac.uk with body "unsubscribe csound"
>
>



-- 
Michael Gogins
Irreducible Productions
http://www.michael-gogins.com
Michael dot Gogins at gmail dot com


Send bugs reports to the Sourceforge bug tracker
            https://sourceforge.net/tracker/?group_id=81968&atid=564599
Discussions of bugs and features can be posted here
To unsubscribe, send email sympa@lists.bath.ac.uk with body "unsubscribe csound"


Date2010-06-07 17:34
FromJim Aikin
Subject[Csnd] Re: Re: MIDI buffer reading
You're right about the time-stamping in a MIDI file, Michael. I don't usually
think of that as having anything to do with MIDI. It's just a sequencer file
interchange format that happens to have been defined by the MMA ... and of
course it has the same range of velocity values and channel numbers as MIDI,
so okay, it's MIDI.

Now that (with Davis's help) I have the algorithm working, I'm going to be
able to use Csound for what I have in mind, which is a general-purpose
real-time keyboard remapping processor. I was thinking of using Pd, but my
Csound programming is better (if only by a little), and I think the Csound
interface is actually preferable in this instance to Pd's.

--Jim Aikin

Date2010-06-07 18:03
FromMichael Gogins
Subject[Csnd] Re: Re: Re: MIDI buffer reading
I'm glad you are finding Csound useful. I think we'd be interested to
hear where your project goes.

Regards,
Mike

On Mon, Jun 7, 2010 at 12:34 PM, Jim Aikin  wrote:
>
> You're right about the time-stamping in a MIDI file, Michael. I don't usually
> think of that as having anything to do with MIDI. It's just a sequencer file
> interchange format that happens to have been defined by the MMA ... and of
> course it has the same range of velocity values and channel numbers as MIDI,
> so okay, it's MIDI.
>
> Now that (with Davis's help) I have the algorithm working, I'm going to be
> able to use Csound for what I have in mind, which is a general-purpose
> real-time keyboard remapping processor. I was thinking of using Pd, but my
> Csound programming is better (if only by a little), and I think the Csound
> interface is actually preferable in this instance to Pd's.
>
> --Jim Aikin
> --
> View this message in context: http://old.nabble.com/MIDI-buffer-reading-tp28800403p28807628.html
> Sent from the Csound - General mailing list archive at Nabble.com.
>
>
>
> Send bugs reports to the Sourceforge bug tracker
>            https://sourceforge.net/tracker/?group_id=81968&atid=564599
> Discussions of bugs and features can be posted here
> To unsubscribe, send email sympa@lists.bath.ac.uk with body "unsubscribe csound"
>
>



-- 
Michael Gogins
Irreducible Productions
http://www.michael-gogins.com
Michael dot Gogins at gmail dot com


Send bugs reports to the Sourceforge bug tracker
            https://sourceforge.net/tracker/?group_id=81968&atid=564599
Discussions of bugs and features can be posted here
To unsubscribe, send email sympa@lists.bath.ac.uk with body "unsubscribe csound"