electro-music.com   Dedicated to experimental electro-acoustic
and electronic music
 
    Front Page  |  Articles  |  Radio
 |  Media  |  Forum  |  Wiki  |  Links  |  Store
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
Getting into audicle/ChucK, 'feature requests'
Post new topic   Reply to topic Moderators: Kassen
Page 1 of 1 [11 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
Author Message
utenzil



Joined: Apr 10, 2006
Posts: 58
Location: maryland

PostPosted: Tue Jan 16, 2007 10:53 am    Post subject: Getting into audicle/ChucK, 'feature requests'
Subject description: w/ example of HID to MIDI, and a .ck to turn a joystick into a MIDI 'note shooter' (all 128)
Reply with quote  Mark this post and the followings unread

Chuck is interesting, there are some fun examples. I'm just getting into it-- I've looked at it for about a half an hour-- so this post might seem dumb, anyway; here's what I'm thinking fwiw, I hope I'm making sense:

One example in particular is the joystick synth control. I like using HID devices to control via midi, and also use midi to generate noodles.

It would be very cool if there were a HID-to-midi example, and/or a function based on a lookup table of MIDI notes where you could do a lookup of the values using a multi char key-- [Note][Octave][sharp/natural/flat], example:
for notes: C2+ C2= C2-

There would be some other identifiers passed in, where the correct 'assembled' MIDI message would be returned for send to a midi out, so for example:

Channel Voice Messages [nnnn = 0-15 (MIDI Channel Number 1-16)]
-------------------------------------------------------------------------

1001nnnn 0kkkkkkk Note On event.
0vvvvvvv This message is sent when a
note is depressed (start).
(kkkkkkk) is the key (note) number.
(vvvvvvv) is the velocity.

1000nnnn 0kkkkkkk Note Off event.
0vvvvvvv This message is sent when a
note is released (ended).
(kkkkkkk) is the key (note) number.
(vvvvvvv) is the velocity.

The function would return the three segments of the message to populated, where you have passed in "NoteOn", C2=, velocityVal, midiChannel.

So you press a note on your joystick, you call the function to send a note message assigned to that button, when button is up you send note off.

A function to facilitate Joystick axes to control ccs would not need a table, you'd pass in the values for controller number and controler value, the function would just package it nicely for sending via ChucK:

1011nnnn 0ccccccc Control Change.
0vvvvvvv This message is sent when a controller
value changes. Controllers include devices
such as pedals and levers.
(ccccccc) is the controller number (0-119).
(vvvvvvv) is the controller value (0-127).
(Controller numbers 120-127 are reserved
as "Channel Mode Messages" ).


Joystick/HID aside, to generate noodles that were more tonal, the note lookup could be called in a function that controlled duration of the notes, so you would call the MIDIMapper lookup function with a "NoteOn" then an increment of now, then "NoteOff". You could have an array that held the lookup keys for notes in a scale, generate numbers to use as ordinals into that array (all numbers would be normalized as needed) to in turn pass into the larger note lookup.

_________________
Utenzil
http://utenzil.com

Last edited by utenzil on Tue Jan 23, 2007 2:24 pm; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
Kassen
Janitor
Janitor


Joined: Jul 06, 2004
Posts: 7678
Location: The Hague, NL
G2 patch files: 3

PostPosted: Tue Jan 16, 2007 11:51 am    Post subject: Reply with quote  Mark this post and the followings unread

Hi, Utenzil, welcome to our crazy little world!

A while ago some people here got a little in the direction that you want to go in, you might want to look at that; feel free to post to it and add your own ideas;
http://electro-music.com/forum/topic-14051.html

Personally I feel that what a "note" is is way open for interpertation and that no real definitive framework can be made but it's nice to see different takes on this.

As for HID to MIDI; I could make you a little example if you'd like. It's true that genearating MIDI messages can be tricky because you need to deal with less then intuitive numbers. There are some plans on the to-do list to make a more accessible interface to this but the to-do list is quite large and our friends at Princeton are quite bussy.

Would it do if I'd make you a example that would -say- translate the first axis of your joystick to a MIDI CC and would have the first button trigger a certain note? You could extend it from there.

_________________
Kassen
Back to top
View user's profile Send private message Send e-mail Visit poster's website
utenzil



Joined: Apr 10, 2006
Posts: 58
Location: maryland

PostPosted: Tue Jan 16, 2007 10:34 pm    Post subject: Reply with quote  Mark this post and the followings unread

Kassen wrote:

Would it do if I'd make you a example that would -say- translate the first axis of your joystick to a MIDI CC and would have the first button trigger a certain note? You could extend it from there.


Hiya-- that would be great, thanks-- sure, I'll extend it, and put it up for others to get also.

_________________
Utenzil
http://utenzil.com
Back to top
View user's profile Send private message Visit poster's website
Kassen
Janitor
Janitor


Joined: Jul 06, 2004
Posts: 7678
Location: The Hague, NL
G2 patch files: 3

PostPosted: Wed Jan 17, 2007 7:03 pm    Post subject: Reply with quote  Mark this post and the followings unread

Here you go;

one button worth of note on-off and one axis mapped to CC7 (that's main volume). All of this on channel1. lots of comments included, do ask if something is still unclear

Code:
// the Hid input event
HidIn hi;

//the hid message
//mesages can have any name but it helps to have good names or there will be confusion
//in this case we need to make sure we don´t confuse the HID and the MIDI mesages.
HidMsg hidmsg;

// open joystick 0, exit on fail
//edit that 0 if you need some other device
//this links your joypad to the "hi" defined above
if( !hi.openJoystick( 0 ) ) me.exit();

// the midi event
MidiOut mout;

// the MIDI message
MidiMsg midimsg;

// open the MIDI device
//edit that 0 if you use multiple devices
//see "chuck --probe"
if( !mout.open( 0 ) ) me.exit();



// infinite event loop
while( true )
{
    // wait on HidIn as event
    hi => now;

    // messages received
    while( hi.recv( hidmsg ) )
    {
   if ( hidmsg.isButtonDown() )
      {
      //this refers to the first button
      if( hidmsg.which == 0)
         {
         //this is a "note on" on the first channel
         //145 would refer tot he second, etc
         144 => midimsg.data1;
         
         //this refers tot he note number
         64 => midimsg.data2;
         
         //this is velocity
         100 => midimsg.data3;
         
         //now that we constructed the whole message, let´s send it
         mout.send( midimsg);
         }
      if( hidmsg.which == 1)
         {
         //code for the second button would go here
         }
      }
      
   if ( hidmsg.isButtonUp() )
      {
      if( hidmsg.which == 0)
         {
         //here we nake a note-off message
         //this bit is the same
         144 => midimsg.data1;

         //take the same note number
         64 => midimsg.data2;
               
         //a velocity of 0 comes down to "note-off"
         0 => midimsg.data3;
               
         //now that we constructed the whole message, let´s send it
         mout.send( midimsg);
         }
         
      }
   if (hidmsg.isAxisMotion() )
      {
      if(hidmsg.which == 0)
         {
         //so here we are talking about the first axis
         
         //we want to translate this to a midi CC
         //176 refers to a CC on the first channel
         
         176 => midimsg.data1;
         
         //let´s take CC7 since it´s used a lot
         
         7 => midimsg.data2;
         
         //axis position will be between -1 and 1
         
         //this makes it between 0 and 1
          0.5 * (1 +hidmsg.axisPosition ) => float A;
         
         //now we scale it for MIDI.
         //clearly this could be written more compact
         //but I wanted to be clear
         //this refers to the number send to the CC
         
         //we also turn that float into a int since MIDI only works with int
         //this loses some data in rounding
         //but that´s midi for you
         
         (A * 127) $ int => midimsg.data3;

         //Phew! constructed another one, let´s send it!
         mout.send( midimsg);

         }
      }
    }
}


_________________
Kassen
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Kassen
Janitor
Janitor


Joined: Jul 06, 2004
Posts: 7678
Location: The Hague, NL
G2 patch files: 3

PostPosted: Wed Jan 17, 2007 7:15 pm    Post subject: Reply with quote  Mark this post and the followings unread

I realise this is throwing you in at the deep end; it would be good to first try to understand how the examples for HID and MIDI work by themselves. This example combines the two things but for a first look at ChucK it's maybe a bit involved.

Also; here is a page on how MIDI works;
http://www.gweep.net/~prefect/eng/reference/protocol/midispec.html

It helps to keep something like that at hand if you want to get serious. If you want to use stuff from there it's good to know that ChucK can also deal with numbers in HEX. It's not ChucK's fault that MIDI is such a weird mess, at least it's cheap and easy to get.

_________________
Kassen
Back to top
View user's profile Send private message Send e-mail Visit poster's website
utenzil



Joined: Apr 10, 2006
Posts: 58
Location: maryland

PostPosted: Wed Jan 17, 2007 9:48 pm    Post subject: Reply with quote  Mark this post and the followings unread

This looks very cool, thanks, Smile I'll need to study for a bit.
_________________
Utenzil
http://utenzil.com
Back to top
View user's profile Send private message Visit poster's website
Kassen
Janitor
Janitor


Joined: Jul 06, 2004
Posts: 7678
Location: The Hague, NL
G2 patch files: 3

PostPosted: Wed Jan 17, 2007 10:24 pm    Post subject: Reply with quote  Mark this post and the followings unread

Cool. Ask questions if you get stuck.
_________________
Kassen
Back to top
View user's profile Send private message Send e-mail Visit poster's website
utenzil



Joined: Apr 10, 2006
Posts: 58
Location: maryland

PostPosted: Thu Jan 18, 2007 12:19 am    Post subject: Reply with quote  Mark this post and the followings unread

It is not quite done yet, but I added something that seems to help: using the same midi message for cc and note would cause a feedback loop, so created two discrete message vars-- it works great now. Thanks for the foundation example, way cool--

Code:

// This ChucK sample converts HID to MIDI.
// It was originally authored by Kassen on the [b][i][color=#255293]electro-music[/color][/i][/b] forum
// It was then modified by Utenzil, who is grateful to Kassen.
   
// the Hid input event
HidIn hidInput;

//the hid message
//messages can have any name but it helps to have good names or there will be confusion
//in this case we need to make sure we don´t confuse the HID and the MIDI mesages.
HidMsg hidMessage;

//open joystick 0, exit on fail
//edit that 0 if you need some other device
//this links your joypad to the "hid input" defined above
//raison d'etre, bail if not found

if( !hidInput.openJoystick( 0 ) ) me.exit();
<<< "+++HID Device detected:'", hidInput.name(), "' ready" >>>;


// TBD possible to do these in a for loop
0 => int firstButton;
1 => int secondButton;
2 => int thirdButton;
// ... for however many buttons ... ?

// XYZ
0 => int firstAxis;
1 => int secondAxis;
2 => int thirdAxis;

// The midi event
MidiOut midiEventOut;

// The MIDI messages to be populated and sent
// Note: Feedback errors occurred by using the
// same message for both note and cc
MidiMsg midiNoteMessage;
MidiMsg midiCCMessage;

// Midi Channel to use
// Assuming MIDI Channel 1
0 => int midiChannel;

// Midi scaling value
127 => int midiNormalVal;

// Midi Note on header bits
144 => int midiNoteInit;

// This creates a "note on" header for the
// message to be sent on the previously selected channel
(midiNoteInit + midiChannel) => int midiNoteDirective;

// The midi note (pitch) value
// TBD select this from an array at the point that
// the button value is known
59 => int currMidiNoteVal;

// The midi note velocity value
int currMidiNoteVelocityVal;
100 => currMidiNoteVelocityVal;

// The midi note off value
0 => int midiNoteOffVal;

// Midi CC header create
176 => int midiCCInit;
(midiCCInit + midiChannel) => int midiCCDirective;

// The midi control change value
//let´s take CC7 since it´s used a lot
int currMidiCCVal;
7 => currMidiCCVal;

//Open the MIDI device
// Assuming 1st device
//edit that 0 if you use multiple devices
//see "chuck --probe"
// Un raison d etre, bail if not found
if( !midiEventOut.open( 0 ) ) me.exit();

<<< "+++MIDI Output to:'", midiEventOut.name(), "' ready" >>>;


// Infinite event loop
while( true )
{
    // wait on HidIn as event
    hidInput => now;

    // HID Messages receive loop
    while( hidInput.recv( hidMessage ) )
    {

   // When joystick button is pressed
   if ( hidMessage.isButtonDown() ){
      // check which button
     hidMessage.which => int currButton;
     
     // TBD, use current button val to lookup assigned note
     if(currButton == firstButton){
   
         midiNoteDirective => midiNoteMessage.data1;
         
         // This refers to the note number
         currMidiNoteVal => midiNoteMessage.data2;
         
         // This is velocity
         currMidiNoteVelocityVal => midiNoteMessage.data3;
         
         //now that we constructed the whole message, let´s send it
         midiEventOut.send(midiNoteMessage);
         }
       }
   

   // When joystick button is released   
   if ( hidMessage.isButtonUp() )
      {
      if( hidMessage.which == firstButton){
        // TBD, use current button val to lookup assigned note
       // here we nake a note-off message
         // this bit is the same
         midiNoteDirective => midiNoteMessage.data1;

         //take the same note number
         currMidiNoteVal => midiNoteMessage.data2;
               
         //a velocity of 0 comes down to "note-off"
         midiNoteOffVal => midiNoteMessage.data3;
               
         //now that we constructed the whole message, let´s send it
         midiEventOut.send( midiNoteMessage);
         }
         
      }
   
   // If the joystick is moved (on either axis)
    if (hidMessage.isAxisMotion() ) {

       hidMessage.which => int currAxis;
      
      // TBD use the current axis value to lookup the assigned data
       if(currAxis == firstAxis){
         // X, right to left stick movement
             
         midiCCDirective => midiCCMessage.data1;
         currMidiCCVal => midiCCMessage.data2;
         
         //Axis position will be between -1 and 1     
         //this makes it between 0 and 1 (normalized)
          0.5 * (1 + hidMessage.axisPosition ) => float normalizedAxis;
         
         //Now we scale it for MIDI.
         //this refers to the number send to the CC
         //we also turn that float into a int since MIDI only works with int
         //this loses some data in rounding
         //but that´s midi for you       
         (normalizedAxis * midiNormalVal) $ int => midiCCMessage.data3;    
         //Phew! constructed another one, let´s send it!
         midiEventOut.send( midiCCMessage);
      
         } // end axis check
         
       } // end check for type of HID
    } // end check for HID msg rcv
} // end infinite loop



_________________
Utenzil
http://utenzil.com
Back to top
View user's profile Send private message Visit poster's website
Kassen
Janitor
Janitor


Joined: Jul 06, 2004
Posts: 7678
Location: The Hague, NL
G2 patch files: 3

PostPosted: Thu Jan 18, 2007 12:37 am    Post subject: Reply with quote  Mark this post and the followings unread

Yeah! That's going very well!

One of the things I like about having a seperate message for note-on and off is that -for monophonic stuff- you can turn the last note off by just chucking 0 to the velocity and re-sending. That saves you house-keeping with regard to the last note send because the mesage itself still stores that. Not usefull at all for polyphonic things.

Anyway, HID-MIDI translation isn't so hard at all, it's mapping controls to parameters that's hard to do well, at least for me. Oh, well, the piano and the sax weren't invented over-night either.

Smile

Great to see you're getting the hang of it so quickly!

_________________
Kassen
Back to top
View user's profile Send private message Send e-mail Visit poster's website
utenzil



Joined: Apr 10, 2006
Posts: 58
Location: maryland

PostPosted: Fri Jan 19, 2007 8:53 am    Post subject: Reply with quote  Mark this post and the followings unread

Ok, I have something that pretty much works the way I want it to, I will post it this weekend.

Fwiw, some background...

I have used Rejoice on WinXP to do hid to midi. It is a great app, is reliable and great for experimenting with gamepads, P5 glove, joysticks, etc. It led me to think about using the X axis to choose octave (bass/left to treble/right), the Y axis to choose velocity (climb/higher, dive/lower) and use the buttons to trigger the notes, sort of like 'shooting the notes' out of a vector space: there is an arc with 11 octaves (numbered 0-10), you 'aim' at your octave left to right, adjust velocity along the Y, and 'shoot' at the note in the octave corresponding to the button. The Z axis sends CC7.

At this point, there are some 'dark spaces' on either side of the arc where you will always hit note 0, I think this is due to normalization.

_________________
Utenzil
http://utenzil.com
Back to top
View user's profile Send private message Visit poster's website
utenzil



Joined: Apr 10, 2006
Posts: 58
Location: maryland

PostPosted: Fri Jan 19, 2007 9:45 pm    Post subject: Reply with quote  Mark this post and the followings unread

[edited] something did not get copied correctly using the code tag, so I followed mosc's advice and used attachment.

So Here it really is. Be careful, you can build up a lot of notes using that 'crosshairs move' trick. Smile

[edit edit] i have some time over lunch to provide some more background.

This is based on a straightforward algorithm for populating an array, and also another for selecting a value from the array, of X by Y items. The values in the given array are simple, consisting of ints 0-127 in a 12 * 12 array (which of course is larger than the number of items but that's ok for now I think) and they are passed literally as part of a midi message to a midi out device. There is also an ability to adjust values 0-127 along a Z axis.

These values could be used 'as is' as indices into an array of 128 sound file names which would then be looked up and in turn passed to a wav or midi file player object, or to an array of MIDI CCs that could in turn be used to automate various VST parameters.

The idea behind the script as it stands is to allow sending midi note on/off messages to a MIDI out using a joystick. I'm using Ableton Live with a 'virtual midi cable', sending notes to VSTis hosted in that software. For completeness, I will put up an MP3 of some of the results when I get a chance.

Thanks again, Kassen, this is very cool, but of course now I got something to work the way I want I might be bothering you more Smile.

Note on velocity adjustment-- velocity is based on the Y axis value at the time the note is played.


midi-hj1.JPG
 Description:
Diagram 1, illustrating operation, describing note selection.
 Filesize:  28 KB
 Viewed:  5900 Time(s)

midi-hj1.JPG



midi-hj2.JPG
 Description:
Diagram 2, illustrating velocity adjustment and CC7 adjustment.
 Filesize:  25.95 KB
 Viewed:  5900 Time(s)

midi-hj2.JPG



midi-hj3.JPG
 Description:
Diagram 3, illustrates octaves arrayed along X axis, describes note selection.
 Filesize:  41.67 KB
 Viewed:  5895 Time(s)

midi-hj3.JPG



hid2midi2.ck
 Description:
ChucK code to convert joystick into midi instrument with full 128 note range.

Download
 Filename:  hid2midi2.ck
 Filesize:  9.82 KB
 Downloaded:  194 Time(s)


_________________
Utenzil
http://utenzil.com
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic Moderators: Kassen
Page 1 of 1 [11 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
e-m mkii

Please support our site. If you click through and buy from
our affiliate partners, we earn a small commission.


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