Hi Everyone,
I’ve been looking around for ways to control Hydra visuals with Sonic Pi. I was mostly focused on OSC but came across a way to send midi_cc messages that seems to work easier. It involves using webMidi on the Hydra side to receive incoming midi cc messages and then you can just send that info from Sonic Pi using the midi_cc function.
First, you need to go to this page and copy the console script:
// register WebMIDI
navigator.requestMIDIAccess()
.then(onMIDISuccess, onMIDIFailure);
function onMIDISuccess(midiAccess) {
console.log(midiAccess);
var inputs = midiAccess.inputs;
var outputs = midiAccess.outputs;
for (var input of midiAccess.inputs.values()){
input.onmidimessage = getMIDIMessage;
}
}
function onMIDIFailure() {
console.log('Could not access your MIDI devices.');
}
//create an array to hold our cc values and init to a normalized value
var cc=Array(128).fill(0.5)
getMIDIMessage = function(midiMessage) {
var arr = midiMessage.data
var index = arr[1]
//console.log('Midi received on cc#' + index + ' value:' + arr[2]) // uncomment to monitor incoming Midi
var val = (arr[2]+1)/128.0 // normalize CC values to 0.0 - 1.0
cc[index]=val
}
Then go to the Hydra Web Editor and open the browser console. I use Chrome but also tried wtih Firefox and it seemed to work as well. Paste the console script into the console and press enter.
Note: I have altered the following line of code in the console script:
var val = (arr[2]+1)/128.0 // normalize CC values to 0.0 - 1.0
to this:
var val = arr[2]
The original line of code converts the midi_cc messages, which have a range from 0 - 127, to a range of 0 -1. it does this because several parameters for Hydra functions take values between 0 and 1. However, I prefer to just take the values between 0 -127 and then convert the values later in the Hydra code.
Once you have entered the console code into the console, Hydra will be ready to receive incoming midi messages from any source.
On the Sonic Pi side, you can send messages to Hydra using the midi_cc function. The midi_cc function takes two arguments, the first is to specify which control number to send to. This number will also need to be included on the Hydra side. The second number is the value you want to send, which needs to be between 0 -127.
Example:
live_loop :mid1 do
midi_cc 0, rrand_i(3, 6) # sends to control 0 a random integer between 3 and 6
sleep 1
end
Hydra code:
(This will pass the random value between 3 and 6 to the shape function which will affect the number of sides of the shape)
shape( () => cc[0]).out() // receives the message from midi_cc 0
As, I said before, several function parameters take a float value between 0 and 1. However, the midi_cc function will round any floating point numbers to the nearest whole number. So if you want to send float values, there are two things you need to do.
On the Sonic Pi end, you can use the val_f: option which will take a floating point value and convert it to a value between 0 - 127 to be consistent with the midi cc values.
live_loop :mid2 do
midi_cc 1, val_f: rrand(0.2, 0.7) # Converts float values to range of 0 -127
sleep 0.25
end
On the Hydra end, when these values are received, it will be received as numbers between 0 and 127 which is not helpful for functions requiring parameters between 0 and 1. So to fix this, you can just divide the cc variable by 127 to convert these values back to the float values.
shape(3, () => cc[1]/127).out() // receives the message from midi_cc 1 and divides it by 127
That is basically all there is to it. Hopefully this can help more people add some visuals to their live coding.
I also put together a video tutorial which goes over how to do all of this: