electro-music.com   Dedicated to experimental electro-acoustic
and electronic music
 
    Front Page  |  Radio
 |  Media  |  Forum  |  Wiki  |  Links
Forum with support of Syndicator RSS
 FAQFAQ   CalendarCalendar   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   LinksLinks
 RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in  Chat RoomChat Room 
 Forum index » DIY Hardware and Software » ChucK programming language
Routing MIDI via ChucK / Using ChucK to Process MIDI Streams
Post new topic   Reply to topic Moderators: Kassen
Page 1 of 1 [5 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
Author Message
MusicMan11712



Joined: Aug 08, 2009
Posts: 1082
Location: Out scouting . . .

PostPosted: Sun Oct 11, 2009 9:58 am    Post subject: Routing MIDI via ChucK / Using ChucK to Process MIDI Streams
Subject description: This thread is for discussions about using ChucK as a MIDI Router.
Reply with quote  Mark this post and the followings unread

Background: When I first met ChucK, I began to explored his friendliness in helping me to route MIDI data from various sources to various destinations. If he was up to the task, I had in mind seeking his assistance to be a real-time, performance oriented coordinator--I tell ChucK what I want on various midi streams, and he follows through faithfully at my command.

To see if he was a good person for the job, I experimented a bit and developed some instructions (ChucK scripts). In case others may be interested, here's one set of instructions. (Hopefully, what I expect of him should be as clear to you as it was to ChucK. If not, I'd be happy to explain.

Note: In order to monitor ChucK's performance during his probationary period, I had him report what he was doing via miniAudicle's console. As I try to do myself, I insisted that ChucK use "user-friendly" terminology.

I tried to keep the instruction pretty straight forward. Hence, the instructions are such that if I want ChucK to do the same for a different source and destination, I tell him early on which MidiInDevice and MidiOutDevice is addressed by that specific memo.

Preliminary report: So far ChucK does pretty much what I ask of him; however, sometimes he seems to nod off, take a break, or maybe get confused--particularly if I ask him to do too much at once. (I may have to filter some of the rapid fire instructions, or, perhaps, he is distracted because I have him reporting to me his every move.)

--Steve

Code:


// ------------------- Hard Coded Midi Echo -------------------
// * Displays (Console Monitor) MIDI I/O device numbers and names
// * Displays MIDI Data Echoed and Friendly MIDI I/O port names

// create array of hexdigits (added 2009-08-15 by MusicMan11712 & Son)
["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"] @=> string hexdigits[];

// number of devices to open for MidiIn and MidiOut(see: chuck --probe)
21 => int MidiInDevice;  // should be DH-100 on MOTU Port 8 IN
21 => int MidiOutDevice; // should be M-GS64 (steel desk)

// friendly names for midi ports
string InPortName[32];
string OutPortName[32];
string FriendlyInPortName[32];
string FriendlyOutPortName[32];

// Midi In Port Names
"MT 4 In 01" @=> InPortName[0];
"MT 4 In 02" @=> InPortName[1];
"MK-499C USB MIDI In" @=> InPortName[2];
"In From MIDI Yoke: 1" @=> InPortName[3];
"In From MIDI Yoke: 2" @=> InPortName[4];
"In From MIDI Yoke: 3" @=> InPortName[5];
"In From MIDI Yoke: 4" @=> InPortName[6];
"In From MIDI Yoke: 5" @=> InPortName[7];
"In From MIDI Yoke: 6" @=> InPortName[8];
"In From MIDI Yoke: 7" @=> InPortName[9];
"In From MIDI Yoke: 8" @=> InPortName[10];
"E-MU XMidi2X2  Midi In 1 " @=> InPortName[11];
"E-MU XMidi2X2  Midi In 2 " @=> InPortName[12];
"MXPXT: Sync In - Out All" @=> InPortName[13];
"Port 1 on PMPXT" @=> InPortName[14];
"Port 2 on PMPXT" @=> InPortName[15];
"Port 3 on PMPXT" @=> InPortName[16];
"Port 4 on PMPXT" @=> InPortName[17];
"Port 5 on PMPXT" @=> InPortName[18];
"Port 6 on PMPXT" @=> InPortName[19];
"Port 7 on PMPXT" @=> InPortName[20];
"Port 8 on PMPXT" @=> InPortName[21];
"" @=> InPortName[22];
"" @=> InPortName[23];
"" @=> InPortName[24];
"" @=> InPortName[25];
"" @=> InPortName[26];
"" @=> InPortName[27];
"" @=> InPortName[28];
"" @=> InPortName[29];
"" @=> InPortName[30];
"" @=> InPortName[31];

// Midi Out Port Names
"MT4 Out 0 (all)" @=> OutPortName[0];
"MT4 Out 01" @=> OutPortName[1];
"MT4 Out 02" @=> OutPortName[2];
"MT4 Out 03" @=> OutPortName[3];
"MT4 Out 04" @=> OutPortName[4];
"MK-449C USB MIDI Out" @=> OutPortName[5];
"Out To Midi Yoke:  1" @=> OutPortName[6];
"Out To Midi Yoke:  2" @=> OutPortName[7];
"Out To Midi Yoke:  3" @=> OutPortName[8];
"Out To Midi Yoke:  4" @=> OutPortName[9];
"Out To Midi Yoke:  5" @=> OutPortName[10];
"Out To Midi Yoke:  6" @=> OutPortName[11];
"Out To Midi Yoke:  7" @=> OutPortName[12];
"Out To Midi Yoke:  8" @=> OutPortName[13];
"Microsoft GS Wavetable SW Synth" @=> OutPortName[14];
"E-MU XMidi2X2 Midi Out 1 " @=> OutPortName[15];
"E-MU XMidi2X2 Midi Out 2 " @=> OutPortName[16];
"MXPXT: Sync In - Out All" @=> OutPortName[17];
"Port 1 on MXPXT" @=> OutPortName[18];
"Port 2 on MXPXT" @=> OutPortName[19];
"Port 3 on MXPXT" @=> OutPortName[20];
"Port 4 on MXPXT" @=> OutPortName[21];
"Port 5 on MXPXT" @=> OutPortName[22];
"Port 6 on MXPXT" @=> OutPortName[23];
"Port 7 on MXPXT" @=> OutPortName[24];
"Port 8 on MXPXT" @=> OutPortName[25];
"" @=> OutPortName[26];
"" @=> OutPortName[27];
"" @=> OutPortName[28];
"" @=> OutPortName[29];
"" @=> OutPortName[30];
"" @=> OutPortName[31];

// Friendly Midi In Port Names
"from P2500 out B" @=> FriendlyInPortName[0];
"from SGX Nitro" @=> FriendlyInPortName[1];
"from MK-499C" @=> FriendlyInPortName[2];
"from DM2MIDI" @=> FriendlyInPortName[3];
"In From MIDI Yoke: 2" @=> FriendlyInPortName[4];
"In From MIDI Yoke: 3" @=> FriendlyInPortName[5];
"In From MIDI Yoke: 4" @=> FriendlyInPortName[6];
"In From MIDI Yoke: 5" @=> FriendlyInPortName[7];
"In From MIDI Yoke: 6" @=> FriendlyInPortName[8];
"In From MIDI Yoke: 7" @=> FriendlyInPortName[9];
"In From MIDI Yoke: 8" @=> FriendlyInPortName[10];
"from P2500 out A" @=> FriendlyInPortName[11];
"from CA-30/CF-10" @=> FriendlyInPortName[12];
"MXPXT: Sync In - Out All" @=> FriendlyInPortName[13];
"from E5000 out A" @=> FriendlyInPortName[14];
"from U-220 # 1 (rack)" @=> FriendlyInPortName[15];
"from XL-1 Orch" @=> FriendlyInPortName[16];
"Port 4 on MXPXT" @=> FriendlyInPortName[17];
"from RA-30 out" @=> FriendlyInPortName[18];
"from VZ-8m # 1" @=> FriendlyInPortName[19];
"from VZ-8m # 2" @=> FriendlyInPortName[20];
"from DH-100 (port 8 in)" @=> FriendlyInPortName[21];
"" @=> FriendlyInPortName[22];
"" @=> FriendlyInPortName[23];
"" @=> FriendlyInPortName[24];
"" @=> FriendlyInPortName[25];
"" @=> FriendlyInPortName[26];
"" @=> FriendlyInPortName[27];
"" @=> FriendlyInPortName[28];
"" @=> FriendlyInPortName[29];
"" @=> FriendlyInPortName[30];
"" @=> FriendlyInPortName[31];

// Friendly Midi Out Port Names
"MT4 Out 0 (all)" @=> FriendlyOutPortName[0];
"to P2500" @=> FriendlyOutPortName[1];
"to SGX Nitro" @=> FriendlyOutPortName[2];
"to P/1+Orchestral" @=> FriendlyOutPortName[3];
"to VZ-8m # 1" @=> FriendlyOutPortName[4];
"MK-449C USB MIDI Out" @=> FriendlyOutPortName[5];
"Out To Midi Yoke:  1" @=> FriendlyOutPortName[6];
"Out To Midi Yoke:  2" @=> FriendlyOutPortName[7];
"Out To Midi Yoke:  3" @=> FriendlyOutPortName[8];
"Out To Midi Yoke:  4" @=> FriendlyOutPortName[9];
"Out To Midi Yoke:  5" @=> FriendlyOutPortName[10];
"Out To Midi Yoke:  6" @=> FriendlyOutPortName[11];
"Out To Midi Yoke:  7" @=> FriendlyOutPortName[12];
"Out To Midi Yoke:  8" @=> FriendlyOutPortName[13];
"Microsoft GS Wavetable SW Synth" @=> FriendlyOutPortName[14];
"to E5000 17 - 32" @=> FriendlyOutPortName[15];
"to CA-30/CF-10/2X2 In 2" @=> FriendlyOutPortName[16];
"MXPXT: Sync In - Out All" @=> FriendlyOutPortName[17];
"to E5000 1 - 16" @=> FriendlyOutPortName[18];
"to U-220 # 1 (rack)" @=> FriendlyOutPortName[19];
"to VZ-8m # 1" @=> FriendlyOutPortName[20];
"to M-GS64 port 1" @=> FriendlyOutPortName[21];
"to M-GS64 port 2" @=> FriendlyOutPortName[22];
"to RA-30" @=> FriendlyOutPortName[23];
"to XL-1 Orchestral" @=> FriendlyOutPortName[24];
"to Port 8 out device" @=> FriendlyOutPortName[25];
"" @=> FriendlyOutPortName[26];
"" @=> FriendlyOutPortName[27];
"" @=> FriendlyOutPortName[28];
"" @=> FriendlyOutPortName[29];
"" @=> FriendlyOutPortName[30];
"" @=> FriendlyOutPortName[31];

// get command line
if( me.args() ) me.arg(0) => Std.atoi => MidiInDevice;

// the midi I/O events
MidiIn min;
MidiOut mout;

// the messages for retrieving and echoing data
MidiMsg msgin;
MidiMsg msgout; //to be used if msgin is changed

// open the MidiInDevice
if( !min.open( MidiInDevice ) ) me.exit();

// print out device that was opened
<<< "MIDI device:", min.num(), " -> ", min.name() >>>;

// open the MidiOutDevice
if (!mout.open(MidiOutDevice) ) me.exit();

// print out device that was opened
<<< "MIDI device:", mout.num(), " -> ", mout.name() >>>;

// infinite time-loop
 while( true )
{
    // wait on the event 'min'
    min => now;

    // get the message(s)
   while ( min.recv(msgin) )
    {   
        // echo midi message inchanged
        mout.send(msgin);
       
            // split midi data into hi and lo hex values (added 2009-08-15 by MusicMan11712 & Son)
            msgin.data1 => int temp1lo;
            16 %=> temp1lo;
            msgin.data1 => int temp1hi;
            16 /=> temp1hi;
            msgin.data2 => int temp2lo;
            16 %=> temp2lo;
            msgin.data2 => int temp2hi;
            16 /=> temp2hi;           
            msgin.data3 => int temp3lo;
            16 %=> temp3lo;
            msgin.data3 => int temp3hi;
            16 /=> temp3hi;

            // display msg.data as hexdigits (modified 2009-08-15 by MusicMan11712 & Son)
             <<< "echoing",
                     hexdigits[temp1hi]+hexdigits[temp1lo] ,
                     hexdigits[temp2hi]+hexdigits[temp2lo] ,
                     hexdigits[temp3hi]+hexdigits[temp3lo],
                   FriendlyInPortName[min.num()],
                   FriendlyOutPortName[mout.num()]   >>>;
     
    }
}

Last edited by MusicMan11712 on Sat Dec 26, 2009 6:20 am; edited 5 times in total
Back to top
View user's profile Send private message
MusicMan11712



Joined: Aug 08, 2009
Posts: 1082
Location: Out scouting . . .

PostPosted: Sun Oct 11, 2009 7:00 pm    Post subject: Screenshot of miniaudicle as realtime midi router Reply with quote  Mark this post and the followings unread

This screenshot shows several Add/Replace/Remove Shred icons which can be used to change midi routings on the fly. Some of the ones here route a usb keyboard to various sound modules. (Upper Left quadrant of screenshot.)

Towards the Lower Left quadrant, a couple of lines of code from one of the scripts are visible. By changing the midi in or out device and replacing the shred, the routing changes on the spot.

In the Upper Right quadrant, the Virtual Machine shows which routings are active.

Shred 1 has data from the Casio DH-100 (Digital Horn) [+ foot pedals] going to a Roland rompler.
Shred 8 has an alternative controller (dm2) sending data to an E-Mu XL-1.
Shred 9 has a riff from the XL-1 going to a Casio VZ-8m.
Shred 11 has a usb keyboard going to an E-Mu P2500.

The Lower Right quadrant, shows the Console Monitor, which in this phase of testing, displays the midi data stream.
Back to top
View user's profile Send private message
Inventor
Stream Operator


Joined: Oct 13, 2007
Posts: 6221
Location: near Austin, Tx, USA
Audio files: 267

PostPosted: Tue Oct 20, 2009 9:32 am    Post subject: Reply with quote  Mark this post and the followings unread

Hey Steve, yes ChucK will struggle if you send out too much text to the console monitor. Too much for my (slow) computer is about a few lines per second. Glad to see you have had good success with your application, though MIDI is one thing that I have not done yet so I wouldn't know much about your application.

Les

_________________
"Let's make noise for peace." - Kijjaz
Back to top
View user's profile Send private message Send e-mail
MusicMan11712



Joined: Aug 08, 2009
Posts: 1082
Location: Out scouting . . .

PostPosted: Sat Dec 26, 2009 5:53 am    Post subject: Reply with quote  Mark this post and the followings unread

Recently I updated some of my code as a step in the direction of processing a midi stream on the fly. I call the process D0/B0 conversion. It was originally developed in the 1980s on a C-64 to take channel pressure data (a two-byte structure, e.g. 0xD0 0x7F) on a Casio DH-100 and change it to CC data (a three-byte structure, e.g. 0xB0 0x01 0x7F) for use on a Korg EX-800 that couldn't handle pressure.

So, far I have inserted 2 parts:
(1) a variable at the top of the script for easy, on-the-fly change of the CC
Code:

01 => int D0B0CC;  // sets the script to convert channel pressure data to CC=01 - mod wheel

(2) a midi data processing section.
Code:

    // get the message(s)
   while ( min.recv(msgin) )
  {   
        // echo midi message unchanged if status byte < 0xA0
        if (msgin.data1 < 0xA0)
            mout.send(msgin);

        // ignore midi message if status byte is between 0xA0 and 0xD0
        else if (msgin.data1 < 0xD0);

        // convert 0xD0 - 0xDF midi messages to 0xB0 01 xx (CC - mod wheel)
        else if (msgin.data1 < 0xE0)
        {   msgin.data2 => msgin.data3;
            D0B0CC => msgin.data2;
            // mask 0xDn channel
            msgin.data1 => int channel;
            0x10 %=> channel;       
            0xB0 + channel => msgin.data1;
            mout.send(msgin);
        }
     }

Right now, its just a test-of-concept design, using if and else if logic. However, more elegant logic can be created. The logic also demonstrates how to filter midi data Data in the range from 0xA0 to 0xDF is filtered out.

It is possible to thin data on the fly, such as CC data. For example, one could send out every third or fourth CC value--making sure to always send out 0x00 and 0x7f.

Another possible application is to have velocity-switch maps or algorithms. At EM09, Don Slepian demonstrated a number of performance techniques including the use of velocity maps--such in an orchestral piece, higher velocities in a certain range or on certain notes trigger percussion.

Anyhow, as long as I did this, I thought I'd share it.

--Steve
Back to top
View user's profile Send private message
MusicMan11712



Joined: Aug 08, 2009
Posts: 1082
Location: Out scouting . . .

PostPosted: Fri Jul 29, 2016 8:32 am    Post subject: Reply with quote  Mark this post and the followings unread

I am revisiting this thread from 6-7 years ago. Why? After completely tearing down my wooden desk synth module stack, I decided to rebuild it, this time without the 8x8 motu midi router (parallel port version) and the audio patch bay. (Way too many cords/cables!!!)

So far, MIDI-OX seems to work sufficiently well, but after seemin some posts on ChucK and MIDI over the past year or so, I began to think again about some possibilities for on-the-fly midi routing and processing using ChucK.

I found my old *.ck scripts from August 2009 and this thread. I figure as long as I am going to give it a go, I might as well look through other related threads here and in the ChucK archives.

So, here are a bunch of related links:
from the Chuck Archives: https://lists.cs.princeton.edu/pipermail/chuck-users/2016-March/thread.html
Controlling shreds via MIDI: http://electro-music.com/forum/topic-46285.html
Shred Organisation [recording MIDI]: http://electro-music.com/forum/topic-42835.html
[Methods for calling note of/off]: http://electro-music.com/forum/topic-41836.html
[MIDI Clock; 3-byte structure issue]: http://electro-music.com/forum/topic-40772.html
Routing MIDI via ChucK / Using ChucK to Process MIDI Streams: http://electro-music.com/forum/topic-37351.html

The idea of controlling shreds via midi sounds intriguing. If its possible, I can imagine having sets of buttons [hardware or virtual buttons on a tablet] sent to a midi-to-ChucK listening port.

Addendum: Anything higher than miniAudicle 0.2 seems to lock up when I try to start the VM despite efforts to troubleshoot. So, I am using it with ChucK version 1.3.5.2 (chimera) for microsoft 32-bit. The scripts still work, though I will be trying to add functionality and improve what I did in 2009.

More links related to real-time processing/routing of MIDI data:
MIDI Canon: http://electro-music.com/forum/post-383872.html#383872
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic Moderators: Kassen
Page 1 of 1 [5 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
 Forum index » DIY Hardware and Software » ChucK programming language
Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Forum with support of Syndicator RSS
Powered by phpBB © 2001, 2005 phpBB Group
Copyright © 2003 through 2009 by electro-music.com - Conditions Of Use