# Controlling Hydra visuals with midi\_cc function

**URL:** <https://in-thread.sonic-pi.net/t/controlling-hydra-visuals-with-midi-cc-function/7378>\
**Category:** Creations & Ideas\
**Created:** [December 28, 2022, 3:21am UTC](https://in-thread.sonic-pi.net/t/controlling-hydra-visuals-with-midi-cc-function/7378 "2022-12-28T03:21:11Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![mrbombmusic](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/mrbombmusic/32/2282_2.png) [@mrbombmusic](https://in-thread.sonic-pi.net/u/mrbombmusic)\
**Post date:** [December 28, 2022, 3:21am UTC](https://in-thread.sonic-pi.net/t/controlling-hydra-visuals-with-midi-cc-function/7378/1 "2022-12-28T03:21:11Z")

</div>

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](https://github.com/ojack/hydra-standalone/blob/master/docs/midi.md) and copy the console script:

```javascript
// 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](https://hydra.ojack.xyz/) 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:

```javascript
 var val = (arr[2]+1)/128.0 // normalize CC values to 0.0 - 1.0

```

to this:

```javascript
 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:

```ruby
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)

```javascript
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.

```ruby
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.

```javascript
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:

[![](https://img.youtube.com/vi/U5Y7w_KcFBo/hqdefault.jpg "Sonic Pi Tutorial - Controlling Hydra Visuals with midi\_cc function") ](https://www.youtube.com/watch?v=U5Y7w_KcFBo)

---

<div class="post-metadata">

**Author:** ![robin.newman](https://avatars.discourse-cdn.com/v4/letter/r/76d3ee/32.png) [@robin.newman](https://in-thread.sonic-pi.net/u/robin.newman)\
**Post date:** [December 28, 2022, 9:21am UTC](https://in-thread.sonic-pi.net/t/controlling-hydra-visuals-with-midi-cc-function/7378/2 "2022-12-28T09:21:07Z")

</div>

Good clear tutorial. Thanks. I have usually used OSC with hydra but this is easy to set up using midi controllers.

---

<div class="post-metadata">

**Author:** ![Relaxnow](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/relaxnow/32/2172_2.png) [@Relaxnow](https://in-thread.sonic-pi.net/u/Relaxnow)\
**Post date:** [December 28, 2022, 9:42am UTC](https://in-thread.sonic-pi.net/t/controlling-hydra-visuals-with-midi-cc-function/7378/3 "2022-12-28T09:42:07Z")

</div>

I can’t wait to try this out. Thank you so much for the tutorial

[![](https://img.youtube.com/vi/FBrdYx3yagA/maxresdefault.jpg "Sonic Pi and Hydra with midi cc take 01") ](https://www.youtube.com/watch?v=FBrdYx3yagA)

I used:

> var val = (arr[2]+1)/128.0 // normalize CC values to 0.0 - 1.0

```ruby
# 230107 0039 Sonic Pi and Hydra with midi_cc take 01
# Saved 230107 0039

# YT https://youtu.be/FBrdYx3yagA
#

# How to setup: OBS HD recording https://www.youtube.com/watch?v=Tb_pjDEdy1c
# How to setup: midi_cc https://in-thread.sonic-pi.net/t/controlling-hydra-visuals-with-midi-cc-function/7378

set_volume! 2

live_loop :time, delay: 0.01 do
  sleep 1
end

live_loop :kick, sync: :time do
  
  stop
  tick
  sample :bd_haus, cutoff: 90, amp: [1,0,0,2,0.2].look
  sample :bd_haus, cutoff: 90, amp: [0,1,0,0,0].look, rate: [2,3,4,5,6].choose
  midi_cc 2,[1,0,0,2,0.2].look
  midi_cc 3, [0,1,0,0,0].look
  sleep 0.25
end

live_loop :hiahat, sync: :time do
  stop
  tick
  use_synth :noise
  use_synth_defaults release: 0.01, amp: [2,0,rrand_i(0.5,2),1,1,0,0].look, rate: 2
  midi_cc 4,[2,0,rrand_i(0.5,2),1,1,0,0].look
  play :c2
  sleep 0.25
end

with_fx :ping_pong, mix: 0.7 do
  live_loop :bass, sync: :time do
    
    stop
    tick
    use_synth :prophet
    res = range(0,0.9,step: 0.1).look
    notes = [:f2,:f2, :f3, :f2,:fs2].look
    #play [:f2,:f2, :f2, :f2,:fs2].look+0, res: res
    play notes+0, res: res
    
    #sleep [1,1,1,1,1].look*2
    sleep [1,0.125,1,0.5,1].look*2*2
    puts midi_cc 1,[1,0.125,1,0.5,1].look*2*2
  end
end

with_fx :reverb, room: 0.9 do
  live_loop :pianoarp, sync: :time do
    
    stop
    tick
    use_synth :piano
    use_synth_defaults release: [0.1,0.04,0.08].choose #+0.1 #+0.2
    
    / chord 1 works/
    use_random_seed 1
    a = 7 #5 #5*3 #5 #7
    rotate = 3
    
    notes = [:f5,:gs5,:c6,:ds6,:f6].rotate(rotate).look-knit(0,a, 12,a, 24,a, 36,a).look
    #notes = [:f5,:gs5,:c6,:ds6,:f6].look
    
    play notes
    puts midi_cc 0,notes#-12-12-12-12-12-12
    
    #play [:f5].look if bools(1,0,1,0,1,1,0).look
    #play [:gs5].look if bools(1,0,1,0,1,1,0).look
    #play [:c6].look if bools(1,0,1,0,1,1,0).look
    #play [:ds6].look if bools(1,0,1,0,1,1,0).look
    #play [:f6].look if bools(1,0,1,0,1,1,0).look
    
    
    #play [:f5].look if bools(1,0).look
    #play [:c5,:ds5,:g5].look if spread(5,10).look
    #play :ds5 if spread(1,7).look
    #play :gs4 if spread(7,9).look
    sleep 0.125
  end
end

# Hydra code YT
# https://hydra.ojack.xyz/?code=QTElMjAlM0QlMjAlMjAoKSUyMCUzRCUzRSUyMGNjJTVCMCU1RC0wLjUlMEFBMiUyMCUzRCUyMCUyMCgpJTIwJTNEJTNFJTIwY2MlNUIwJTVELTAuNSotMSUwQUIxJTIwJTNEJTIwJTIwKCklMjAlM0QlM0UlMjBjYyU1QjElNUQqNCUwQUIyJTIwJTNEJTIwJTIwKCklMjAlM0QlM0UlMjBjYyU1QjElNUQqNCotMSUwQUMxJTIwJTNEJTIwKCklMjAlM0QlM0UlMjBjYyU1QjIlNUQqNCoyJTBBQzIlMjAlM0QlMjAoKSUyMCUzRCUzRSUyMGNjJTVCMyU1RCoxNiUwQUQxJTIwJTNEJTIwKCklMjAlM0QlM0UlMjBjYyU1QjQlNUQqMjAlMEFvc2MoMSUyQzAuNSUyQzIpLm11bHQoc2hhcGUoNCUyQ0IxJTJDMCkuc2Nyb2xsKEExJTJDQjEpJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwLmFkZChzaGFwZSg0JTJDQjElMkMwKS5zY3JvbGwoQTElMkNCMikpKSUwQSUyMCUyMC5vdXQobzApJTIwJTBBJTBBb3NjKDIlMkMwLjUlMkMyKS5tdWx0KHNoYXBlKDIlMkNDMSUyQzApLnNjcm9sbChDMSUyQ0MyKSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMC5hZGQoc2hhcGUoOTklMkNDMiUyQzApLnNjcm9sbChDMSUyQ0MyKSkpJTBBJTIwJTIwLm91dChvMSklMjAlMEElMEElMEFub2lzZSgyJTJDMC4wMTUlMkM1KS5kaWZmKCUwQSUyMCUyMHZvcm9ub2koMiUyQzAuMSUyQzIwKSUwQSUyRiUyRiUyMCUyMHNoYXBlKDMlMkNEMSUyQzApJTBBJTIwJTIwJTJGJTJGLnNjcm9sbChEMSUyQ0QxKSUwQSUyMCUyMC5zY2FsZShEMSklMEElMjAlMjAuc2Nyb2xsKDAuNzUlMkMwLjc1KSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCklMEElMjAlMjAlMkYlMkYubHVtYSgwLjUpJTBBJTBBJTIwJTIwLm91dChvMiklMjAlMEElMEFzcmMobzApLmJsZW5kKHNyYyhvMSkuYmxlbmQobzIpKS5jb2xvcmFtYSgxJTJDMCUyQzElMkMpLmludmVydCgwLjgpLm91dChvMyklMEElMEFyZW5kZXIobzMp

```

By the way the Chrome Console tend to create errors when trying to recreate connection. I dont know how to avoid that, but you can reset Chrome by closing all chrome browsers, I found out.

---

<div class="post-metadata">

**Author:** ![njmm](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/njmm/32/2464_2.png) [@njmm](https://in-thread.sonic-pi.net/u/njmm)\
**Post date:** [December 28, 2022, 11:34am UTC](https://in-thread.sonic-pi.net/t/controlling-hydra-visuals-with-midi-cc-function/7378/4 "2022-12-28T11:34:59Z")

</div>

Very nice 👍 👍  
With this, a web browser is the only software needed along Sonic Pi to have a full music+visuals setup. I’m new to Pi and I’m surprised at how easily achievable this is. I’n eager to try it.  
Thanks!

---

<div class="post-metadata">

**Author:** ![robin.newman](https://avatars.discourse-cdn.com/v4/letter/r/76d3ee/32.png) [@robin.newman](https://in-thread.sonic-pi.net/u/robin.newman)\
**Post date:** [December 31, 2022, 10:45pm UTC](https://in-thread.sonic-pi.net/t/controlling-hydra-visuals-with-midi-cc-function/7378/5 "2022-12-31T22:45:07Z")

</div>

Thought I’d do a colourful hydra sketch using midi links and audio from Sonic Pi to control it. Uses the midi links discussed above.

[![](https://img.youtube.com/vi/Du0yLoDYHOs/maxresdefault.jpg "Sonic Pi Hydra 2") ](https://www.youtube.com/watch?v=Du0yLoDYHOs)

code for sketch and Sonic Pi is [here](https://gist.github.com/rbnpi/9fa79ab7305e022727e20d456a8ae8f8)

---

<div class="post-metadata">

**Author:** ![Prof1220](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/prof1220/32/1150_2.png) [@Prof1220](https://in-thread.sonic-pi.net/u/Prof1220)\
**Post date:** [January 3, 2023, 7:44am UTC](https://in-thread.sonic-pi.net/t/controlling-hydra-visuals-with-midi-cc-function/7378/6 "2023-01-03T07:44:23Z")

</div>

Thank you for this tutorial. I did something similar(in Italian) for my students (12-14 yo). I did not tested it yet with them in the classroom, but I think that for kids this is a much more easy way to integrate Sonic pi and Hydra, without the need of installing Atom and Hydra packages. I will improve my tutorial with some of your suggestions, thanks! And I will give you a feedback as soon as our project is finished.

---

<div class="post-metadata">

**Author:** ![EdgarDelgadoVega](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/edgardelgadovega/32/3083_2.png) [@EdgarDelgadoVega](https://in-thread.sonic-pi.net/u/EdgarDelgadoVega)\
**Post date:** [January 11, 2023, 2:06am UTC](https://in-thread.sonic-pi.net/t/controlling-hydra-visuals-with-midi-cc-function/7378/8 "2023-01-11T02:06:13Z")

</div>

Great tutorial!  
Thanks @mrbombmusic

---

<div class="post-metadata">

**Author:** ![vision-board](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/vision-board/32/2482_2.png) [@vision-board](https://in-thread.sonic-pi.net/u/vision-board)\
**Post date:** [January 19, 2023, 2:37pm UTC](https://in-thread.sonic-pi.net/t/controlling-hydra-visuals-with-midi-cc-function/7378/9 "2023-01-19T14:37:17Z")

</div>

Seems like this midi\_cc method is working for everyone, but I can’t get it to work on my end.  
I tried @mrbombmusic’s code/video on a Windows and on a Mac, on Chrome on both systems (and Firefox/Edge on Windows only). On both ends, I get stuck here:

 ![chrome_uOnemAw06u](https://europe1.discourse-cdn.com/flex017/uploads/sonic_pi/original/2X/7/7508d716d02e4874ab2f1d2bbd1585579415626d.png)

And I get no console activity when I uncomment this line

`//console.log('Midi received on cc#' + index + ' value:' + arr[2]) // uncomment to monitor incoming Midi`

I also tried some of the other codes on this thread, no luck.

My hypothesis: The problem rests on Hydra/Chrome’s side and not on Sonic Pi, as I downloaded a Midi Viewer and I see Sonic Pi is successfully sending out data to the specified channel.

Not trying to turn this thread into a troubleshooting session but I thought it would be worth reporting to see if other people are running into the same issue.

My question to the thread is: Do you see anything on the Sonic Pi side’s IO section that would confirm that Web Midi is active and that SP is sending midi there? I have a couple of other MIDI-compatible devices on my Windows and I suspect it could cause problems, but it does not explain why I am running into the same problem on Mac?

---

<div class="post-metadata">

**Author:** ![Relaxnow](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/relaxnow/32/2172_2.png) [@Relaxnow](https://in-thread.sonic-pi.net/u/Relaxnow)\
**Post date:** [January 19, 2023, 3:03pm UTC](https://in-thread.sonic-pi.net/t/controlling-hydra-visuals-with-midi-cc-function/7378/10 "2023-01-19T15:03:07Z")

</div>

I use loopmidi as midi out in Sonic Pi on Windows  
[https://www.tobias-erichsen.de/software/loopmidi.html](https://www.tobias-erichsen.de/software/loopmidi.html)  
So perhaps install loopmidi + reboot Sonic Pi might solve this?

 ![loopmidi](https://europe1.discourse-cdn.com/flex017/uploads/sonic_pi/original/2X/e/e4361c064acfc44cf49b70779bec47baa5d5d8b7.jpeg)

---

<div class="post-metadata">

**Author:** ![vision-board](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/vision-board/32/2482_2.png) [@vision-board](https://in-thread.sonic-pi.net/u/vision-board)\
**Post date:** [January 19, 2023, 5:24pm UTC](https://in-thread.sonic-pi.net/t/controlling-hydra-visuals-with-midi-cc-function/7378/11 "2023-01-19T17:24:09Z")

</div>

That seems to have done the trick. Thank you! 🥳
