Midi questions
Midi questions
I'm looking for a way to programmatically send a note off message. note out works but I am running into horrendous timing problems which I can't seem to solve. Are there any examples of how to send note o and note off messages using the midiout function?
Thanks,
Joe B
Thanks,
Joe B
Re: Midi questions
Hi Joe, the two functions shouldn't make a difference in your timing (or the timing imposed by Lemur, minimum 16ms) and there are a few ways to go about a note off.
I use something like this in a script, it's a noteon (0x90) to device 0, midi channel 0 with a velocity of 0.
I usually setup a lastnote variable at the output of one noteon event though the use of only one noteon function used throughout the entire template.
-J
I use something like this in a script, it's a noteon (0x90) to device 0, midi channel 0 with a velocity of 0.
Code: Select all
lastnote=MIDINOTENUMBER
outputdevice=0; // or set somewhere else in template
midiout(outputdevice,{0x90,lastnote%128,0});
-J
joebataz wrote:I'm looking for a way to programmatically send a note off message. note out works but I am running into horrendous timing problems which I can't seem to solve. Are there any examples of how to send note o and note off messages using the midiout function?
Thanks,
Joe B
Dashboard gear control templates: User 112 Idx :: LModIt Lite :: SVG image converter for Lemur Canvas
Re: Midi questions
Thanks analog, I will give that a try. Here's the setup:
I have a DMX box which controls lights and other effects. There is a standalone application which responds to MIDI notes on channels 15 and 16. Channel 15 is a Bank select and channel 16 is a preset select within the selected bank. You build presets across 512 DMX addresses and then save that as a preset. There is also a VST plug-in which works inside of Logic, Live, Cubase, etc. I can do some pretty sophisticated preset changes as fast as 1/64 notes at 180 BPM. Thats great and wonderful and it works like a charm except you can't really change it on the fly, i.e. a performer goes to the wrong spot and you want to use a different light. This is because the VST plug-in doesn't respond to MIDI at all, like the standalone application does!
So I developed a Lemur application that stores and fires off bank/preset pairs in a sequence but where I could fire them off relatively quickly in the VST and using a MIDI keyboard with the standalone, the Lemur template connected to the standalone is very erratic. Running thru a sequence automatically will cause inconsistent firing of the presets. Sometimes a preset will fire as it should and then the next time thru it won't. I have written all kinds of timing loops and it just doesn't work. If I step thru the sequence one at at time using a button all works as it should, even as quickly as my finger can tap, it seems to work fine. But of course that blows away the precise timing I'm looking for.
Again, thanks for the response and I'll keep you informed of the progress (or lack thereof)
joeb
I have a DMX box which controls lights and other effects. There is a standalone application which responds to MIDI notes on channels 15 and 16. Channel 15 is a Bank select and channel 16 is a preset select within the selected bank. You build presets across 512 DMX addresses and then save that as a preset. There is also a VST plug-in which works inside of Logic, Live, Cubase, etc. I can do some pretty sophisticated preset changes as fast as 1/64 notes at 180 BPM. Thats great and wonderful and it works like a charm except you can't really change it on the fly, i.e. a performer goes to the wrong spot and you want to use a different light. This is because the VST plug-in doesn't respond to MIDI at all, like the standalone application does!
So I developed a Lemur application that stores and fires off bank/preset pairs in a sequence but where I could fire them off relatively quickly in the VST and using a MIDI keyboard with the standalone, the Lemur template connected to the standalone is very erratic. Running thru a sequence automatically will cause inconsistent firing of the presets. Sometimes a preset will fire as it should and then the next time thru it won't. I have written all kinds of timing loops and it just doesn't work. If I step thru the sequence one at at time using a button all works as it should, even as quickly as my finger can tap, it seems to work fine. But of course that blows away the precise timing I'm looking for.
Again, thanks for the response and I'll keep you informed of the progress (or lack thereof)
joeb
Re: Midi questions
ok cool Joeb, if you haven't already put a midi monitor in between your DMX and the Lemur..
and check the values. watch them, do the math and make sure that they conform.
I found bugs in a template where sometimes I would get parameter changes, and other times it was not or doing weird stuff.
and you may already be doing this.. but
You've got to be very careful and enforce byte length of any value going out using MIDIout..
otherwise some values will begin to add more bytes out.
I do this using the floor function and a bitmasks.
So for instance in one of my older midiouts sending to various midi channels, everything was fine until I began to increment the channel count.
i had:
[updated outchan 0-15]
but since the function 0x9 was added with variable 'c' it sometimes produced more than one byte,
this carried more data into the midioutput than desired and I found it by monitoring midi in the computer
after LemurDaemon before the synth.
so I had to write (and outchan variable source is floor(slider.x * 16) passed along to this function):
and I had to correct all midiout functions to implement.. but it wasn't a problem since I call only a few midiout wrapping functions throughout the entire template.
For the gory details, check out my miniKeysNoteGen template.
hope this helps in some way.
good luck on your design! and yes I know that needing to figure out these techniques can be very frustrating.
-J
and check the values. watch them, do the math and make sure that they conform.
I found bugs in a template where sometimes I would get parameter changes, and other times it was not or doing weird stuff.
and you may already be doing this.. but
You've got to be very careful and enforce byte length of any value going out using MIDIout..
otherwise some values will begin to add more bytes out.
I do this using the floor function and a bitmasks.
So for instance in one of my older midiouts sending to various midi channels, everything was fine until I began to increment the channel count.
i had:
[updated outchan 0-15]
Code: Select all
c=floor(outchan*15); //channel tied to a slider with only floor(outchan*15)
midiout(0,{0x90+c,NoteValue,Velocityvalue})
this carried more data into the midioutput than desired and I found it by monitoring midi in the computer
after LemurDaemon before the synth.
so I had to write (and outchan variable source is floor(slider.x * 16) passed along to this function):
Code: Select all
decl c=floor(outchan) & 0xF; // ensure our slider value is only half a byte
decl ch=floor(0x90+c);// set the function and add the channel. additional floor func may be overkill
midiout(0, {ch,NoteValue,Velocityvalue} );
For the gory details, check out my miniKeysNoteGen template.
hope this helps in some way.
good luck on your design! and yes I know that needing to figure out these techniques can be very frustrating.
-J
Last edited by analog604 on 23 Mar 2012 11:41, edited 1 time in total.
Dashboard gear control templates: User 112 Idx :: LModIt Lite :: SVG image converter for Lemur Canvas
Re: Midi questions
Thanks, I'll take a look at the template. Yes, I do have midi monitor running and I'm getting what I would expect but the app I'm sending the midi to just doesn't respond correctly or consistently.
*%#%&^&$#@^&$@&##*#%........
oh well, its a shame because everything, storing, retrieving, manually stepping thru work perfectly.
joeb
*%#%&^&$#@^&$@&##*#%........
oh well, its a shame because everything, storing, retrieving, manually stepping thru work perfectly.
joeb
Re: Midi questions
Hi -J
One issue I see in your code is the channel addition section - adding hex and decimal: not sure how it would resolve that . . .
Also the 0x90 is channel 1 so range is 0 - 15 not 1 - 16 ; 0x90 +(dec)15 =9F Channel 16 but 0x90 +(dec)16 =0x100
Joe - don't quite follow you - how do you get the VST to do 1/64th at 180bpm if it does not respond to MIDI at all?
Again I find it very difficult to offer anything solid without seeing some code - how are you doing the sequencing, timing loops etc
What connectivity are you using? hardwired or wi-fi/adhoc? Latency and jitter is far less likely when wired.
Cheers
MM
One issue I see in your code is the channel addition section - adding hex and decimal: not sure how it would resolve that . . .
Also the 0x90 is channel 1 so range is 0 - 15 not 1 - 16 ; 0x90 +(dec)15 =9F Channel 16 but 0x90 +(dec)16 =0x100
Joe - don't quite follow you - how do you get the VST to do 1/64th at 180bpm if it does not respond to MIDI at all?
Again I find it very difficult to offer anything solid without seeing some code - how are you doing the sequencing, timing loops etc
What connectivity are you using? hardwired or wi-fi/adhoc? Latency and jitter is far less likely when wired.
Cheers
MM
iMac 2.8G i7 12G 10.6.8/10.7.2, Legacy Dexter/Lemur, Liine Lemur/iPad2, KMI SoftStep, 12Step & QuNeo , B-Controls, Mackie C4 etc
MaxMSP, Live Suite, Native Instrument stuff, etc Modified Virtual Guitar System etc All Projects/Modules © CC-BY-NC-SA[*][/b]
MaxMSP, Live Suite, Native Instrument stuff, etc Modified Virtual Guitar System etc All Projects/Modules © CC-BY-NC-SA[*][/b]
Re: Midi questions
Not my code. The following is in an OnFrame script at the top level in the template and is the piece of code causing the timing issues. The code; times > lastTime + 0.03 is the area where I try to get the timing to work. This gives the best results, about 20%. I've quit all the software running except Midi Monitor, Lemur Editor and the standalone which controls the DMX box. Everything appears exactly as it should in Midi Monitor but I still get inconsistencies with the operation of the box. I am using direct wired connection. As far as the VST I set it up as the "instrument" in channels 15 & 16 in Live. I haven't been able to get the VST to respond any Midi that doesn't come from the Midi track itself. I've contacted the manufacturer and gave him detailed explanations of how I had everything setup and they are considering adding midi out to the standalone which would allow me to poll for when the midi has been received and executed.
Thanks for the help!
if((PBBumpA.x == 1) && (PBSendPresetStateA.x == 1) && (CurFrameA<sizeof(A_SeqBank)))
{
timeClock = floor(time-timeMark) + time%.25;
if((A_SeqTime[CurFrameA] < timeClock))
{
if(times > lastTime + 0.03)
{
noteout(0,A_SeqBank[CurFrameA],127,15);
noteout(0,A_SeqBank[CurFrameA],0,15);
setattribute(A_CurBName,'content',BankName[A_SeqBank[CurFrameA]]);
setattribute(A_CurPName,'content',getPresetName(A_SeqBank[CurFrameA],A_SeqPre[CurFrameA]));
if(CurFrameA == 0)
{
setattribute(A_PrvBName,'content','SEQUENCE');
setattribute(A_PrvPName,'content','START OF');
}
else
{
setattribute(A_PrvBName,'content',BankName[A_SeqBank[CurFrameA-1]]);
setattribute(A_PrvPName,'content',getPresetName(A_SeqBank[CurFrameA-1],A_SeqPre[CurFrameA-1]));
}
if(CurFrameA == sizeof(A_SeqBank)-1)
{
setattribute(A_NxtBName,'content','SEQUENCE');
setattribute(A_NxtPName,'content','END OF');
}
else
{
setattribute(A_NxtBName,'content',BankName[A_SeqBank[CurFrameA+1]]);
setattribute(A_NxtPName,'content',getPresetName(A_SeqBank[CurFrameA+1],A_SeqPre[CurFrameA+1]));
}
noteout(0,A_SeqPre[CurFrameA],127,16);
noteout(0,A_SeqPre[CurFrameA],0,16);
lastTime = timeClock;
CurFrameA ++;
}
times = timeClock;
}
}
Thanks for the help!
if((PBBumpA.x == 1) && (PBSendPresetStateA.x == 1) && (CurFrameA<sizeof(A_SeqBank)))
{
timeClock = floor(time-timeMark) + time%.25;
if((A_SeqTime[CurFrameA] < timeClock))
{
if(times > lastTime + 0.03)
{
noteout(0,A_SeqBank[CurFrameA],127,15);
noteout(0,A_SeqBank[CurFrameA],0,15);
setattribute(A_CurBName,'content',BankName[A_SeqBank[CurFrameA]]);
setattribute(A_CurPName,'content',getPresetName(A_SeqBank[CurFrameA],A_SeqPre[CurFrameA]));
if(CurFrameA == 0)
{
setattribute(A_PrvBName,'content','SEQUENCE');
setattribute(A_PrvPName,'content','START OF');
}
else
{
setattribute(A_PrvBName,'content',BankName[A_SeqBank[CurFrameA-1]]);
setattribute(A_PrvPName,'content',getPresetName(A_SeqBank[CurFrameA-1],A_SeqPre[CurFrameA-1]));
}
if(CurFrameA == sizeof(A_SeqBank)-1)
{
setattribute(A_NxtBName,'content','SEQUENCE');
setattribute(A_NxtPName,'content','END OF');
}
else
{
setattribute(A_NxtBName,'content',BankName[A_SeqBank[CurFrameA+1]]);
setattribute(A_NxtPName,'content',getPresetName(A_SeqBank[CurFrameA+1],A_SeqPre[CurFrameA+1]));
}
noteout(0,A_SeqPre[CurFrameA],127,16);
noteout(0,A_SeqPre[CurFrameA],0,16);
lastTime = timeClock;
CurFrameA ++;
}
times = timeClock;
}
}
Re: Midi questions
Hi Macciza, I've been thinking about what you said about adding hex and decimal.
Although it worked after masking the values, I think using a bitwise OR function may be another (preferred?) way to go about it.
I used the updated method in an existing template last night with success.
decl c=floor(outchan) & 0xF; // ensure our slider value is only half a byte
midiout(0, { 0x90 | c , NoteValue, Velocityvalue} );
Joeb have you made progress with the template?
cheers
J
Although it worked after masking the values, I think using a bitwise OR function may be another (preferred?) way to go about it.
I used the updated method in an existing template last night with success.
decl c=floor(outchan) & 0xF; // ensure our slider value is only half a byte
midiout(0, { 0x90 | c , NoteValue, Velocityvalue} );
Joeb have you made progress with the template?
cheers
J
Macciza wrote:One issue I see in your code is the channel addition section - adding hex and decimal: not sure how it would resolve that . . .
Also the 0x90 is channel 1 so range is 0 - 15 not 1 - 16 ; 0x90 +(dec)15 =9F Channel 16 but 0x90 +(dec)16 =0x100
Last edited by analog604 on 29 Mar 2012 13:20, edited 1 time in total.
Dashboard gear control templates: User 112 Idx :: LModIt Lite :: SVG image converter for Lemur Canvas
Re: Midi questions
In thinking some more about this, I wonder if the app may not be able to handle the midi data changes as fast as it is being sent.
At one point a few months ago during testing, I had Lemur sending midi as fast as it could with no output timing control.
The note data was going to a two different brands of synthesizers. During the course of this I had managed to make both of them unresponsive after which they had to be power cycled! One more so than the other (a mono voice synth).
This was only with note data, no exotic control changes.
So I programmed a timing loop to send data slower, (at 120BPM: 1/64th (~312ms) or 1/32 at 120BPM) and they began to respond more consistently. Still every once in a while there was a 'hiccup' where my in Lemur output scope would visible halt for 1/4 of a second or so then continue.
It makes me wonder if other apps in the background that may cause hiccups occasionally (I'm guessing at the last one.. no root/developer access on my iPad right now).
-J
At one point a few months ago during testing, I had Lemur sending midi as fast as it could with no output timing control.
The note data was going to a two different brands of synthesizers. During the course of this I had managed to make both of them unresponsive after which they had to be power cycled! One more so than the other (a mono voice synth).
This was only with note data, no exotic control changes.
So I programmed a timing loop to send data slower, (at 120BPM: 1/64th (~312ms) or 1/32 at 120BPM) and they began to respond more consistently. Still every once in a while there was a 'hiccup' where my in Lemur output scope would visible halt for 1/4 of a second or so then continue.
It makes me wonder if other apps in the background that may cause hiccups occasionally (I'm guessing at the last one.. no root/developer access on my iPad right now).
-J
joebataz wrote:Thanks, I'll take a look at the template. Yes, I do have midi monitor running and I'm getting what I would expect but the app I'm sending the midi to just doesn't respond correctly or consistently.
*%#%&^&$#@^&$@&##*#%........
oh well, its a shame because everything, storing, retrieving, manually stepping thru work perfectly.
joeb
Dashboard gear control templates: User 112 Idx :: LModIt Lite :: SVG image converter for Lemur Canvas
Re: Midi questions
Yes and no on the progress. I've totally redone the template, going from 16X16 (banks vs presets) to 24 X 32. I pulled all the storage vars and have put code into the buttons themselves instead of at the global level. But of course there is the timing issue which continues to be a problem. I think analog604 is correct with it being a combination of factors. I have moved to another sound app, away from Traktor which is allowing me to put midi into the app instead of using the Live/Logic method and which also has the added benefit of allowing me to control the VST from MIDI (Lemur) while the sound app is running. I've also been in touch with the developer and he is putting together a module that will send me a couple of the midi things I need to get the timing tweaked better (BPM, beats)
As far as the DMX controller app the developer there says that the "standard" is to be able to MIDI data at 25 frames a second which puts me at 40ms which is about where I saw the best results with repeatability, so that is my new target timing count. We'll see.....
Thanks again for the feedback!
joeb
As far as the DMX controller app the developer there says that the "standard" is to be able to MIDI data at 25 frames a second which puts me at 40ms which is about where I saw the best results with repeatability, so that is my new target timing count. We'll see.....
Thanks again for the feedback!
joeb