Author |
Message |
clembie
Joined: May 16, 2007 Posts: 4 Location: Brooklyn, NY
|
Posted: Fri May 18, 2007 12:46 pm Post subject:
MIDI Learn Functionality Subject description: Implementing a MIDI learn function as part of a patch |
 |
|
Confession: I'm both new to Chuck as well as being a novice programmer.
I'm trying to build a(n exceptionally un-sexy) patch in ChucK to dynamically route signals from my MIDI controller to a PODxt (if you don't know, don't worry; It's a guitar gadget), whose parameters can be controlled via MIDI signals, but whose physical interface is complete shite.
The PODxt both receives as well as sends MIDI signals, so I want my patch to listen for signals from both. The PODxt MIDI signals will be used to verify that control is successful (nevermind that for now), but also, when the patch is in "learn" mode, indicate which parameter should be mapped to which controller parameter so all the performer has to do is:
- initiate learn mode
- indicate which parameter is being mapped by moving it on the PODxt
- indicate which controller is mapping to it by moving the controller
- exit learn mode
I'm going to keep a mapping table (probably a multi-dimensional array?) for map state, and learn-mode should be able to alter this table.
Here's where I'm stuck:
Code: |
MidiIn cntrlmin;
MidiIn podxtin;
MidiOut podxtout;
MidiMsg msg;
1 => int cntrlinport; // port in from controller
2 => int podxtinport; // port in from pod
1 => int podxtportout; // port out to PODxt
1 => int debug; // turn on lots of string printing
// insert some sort of mapping table here...
false => int MACHINE_IS_LEARNING;
if( !cntrlmin.open(cntrlinport) ) { me.exit; }
if( !podxtin.open(podxtinport) ) { me.exit; }
if( !podxtout.open(podxtportout) ) { me.exit; }
// learn function
fun int machineLearn () {
while( MACHINE_IS_LEARNING ) {
// get PODxt parameter (data2) to map to
// get controller (data2) to map from
// update mapping table
false => MACHINE_IS_LEARNING; // get out, we're done
}
// if successful, return 0, else return 1
}
while( true ) {
cntrlmin => now;
while( cntrlmin.recv(msg) ) {
if( debug == 1 ) { <<<"Received msg: ",msg.data1,msg.data2,msg.data3>>>; }
if( (msg.data1 == 144) && (msg.data2 == 36) ) {
true => MACHINE_IS_LEARNING;
// from here we have to go to some MIDI learn function
// like machineLearn(), above... But I keep crashing Chuck!
}
// based on mapping table, change msg.data2 to appropriate
podxtout.send(msg);
}
}
|
I'm ready to hear that I'm just too much of a noob to be writing state machines. But I'm not sure whether I'm supposed to be making a function call, or sporking a shred or what when we get the signal to start learning. I can see running a concurrent shred that is always listening and "learning" but only updates the mapping table when MACHINE_IS_LEARNING == true, but that wouldn't be terribly efficient.
I'm assuming that I need to loop something like this inside the function call:
Code: |
while ( podxtinport.recv(msg) ) {
while( cntrlmin.recv(msg) ) {
// get messages and update local variables
// when the signal to exit learn mode is received, update table
}
}
|
Will I also need to chuck one of those MidiIn objects to now? Advancing time is still a hazy issues for me. |
|
Back to top
|
|
 |
Kassen
Janitor


Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Fri May 18, 2007 1:26 pm Post subject:
|
 |
|
Well, you should feel right at home. ChucK is actually meant as a teaching tool for novice programers so welcome!
And yes; chucking a midi input to now mean "this shred now has to wait for MIDI input before doing anything" (likely it'll be parsing that input).
If I understand what you are trying to do corectly then yes; a lookup array would be a good solution. When the program is in "learn" mode it could extract the channel and cc# from one message, map that to a apropriate channel and cc that it'd get from the next messsage and from there on it would use that data to turn one into the other.
You could use a 16 by 128 array for this, representing 16 MIDI channels with each 128 CC's. Likely you can get away with that and a extra field to hold the Pod's MIDI channel because I imagine something like a Pod only uses one channel? _________________ Kassen |
|
Back to top
|
|
 |
clembie
Joined: May 16, 2007 Posts: 4 Location: Brooklyn, NY
|
Posted: Fri May 25, 2007 6:32 pm Post subject:
listen to 2 MIDI inputs at once |
 |
|
Thanks, Kassen! I'm making progress...
How do I make chuck listen to two different MIDI inputs at once?
I have to poll them both, don't I? I can't chuck them both to now, right? |
|
Back to top
|
|
 |
clembie
Joined: May 16, 2007 Posts: 4 Location: Brooklyn, NY
|
|
Back to top
|
|
 |
Kassen
Janitor


Joined: Jul 06, 2004 Posts: 7678 Location: The Hague, NL
G2 patch files: 3
|
Posted: Sat May 26, 2007 9:43 am Post subject:
Re: listen to 2 MIDI inputs at once |
 |
|
clembie wrote: | Thanks, Kassen! I'm making progress...
How do I make chuck listen to two different MIDI inputs at once?
I have to poll them both, don't I? I can't chuck them both to now, right? |
That's right, you can't (currently) make one shred wait for two ports. You don't need to either, if I understand it all corectly the two ports will ahve very different relationships to your program with different functionality behind both so that's not so bad. Do remember to give the ports and the mesages nice and sensible names or you'll get confused (ok, I messed that up myself in the past and *I* got confused...)
I had a quick glance at your code and it all looks very clean and structured to me. I'd say you are on the right track. Personally I feel that there is no better way of learning then starting out with a simple but usefull project. _________________ Kassen |
|
Back to top
|
|
 |
|