New Tool: Monome For Renoise Without Duplex

using maxmsp 5 as a go between for monome control of renoise and renoise control of monome all via osc.

pattern sequencer matrix mutes and prefx volume controls on an 8x8 grid (currently monome64 only)

osc data flow:

other minor things

Monome64_MaxMSP_Renoise_v2.zip & monomeserial
(monomecontrol objects for maxmsp required if running from source)

Hey samBiotic - no linebreaks in the [code] ?

I experienced that too the last time I posted some code - perhaps the forum has a bug…

fixed!

Why the dependency on maxmsp?

Why not?

If people use MaxMSP and have fun coding with Renoise. I say good times.

There isn’t one. You could create what I have with a larger stand alone renoise tool.
I’m just better at it than lua scripting.
You can evaluate code with the new API at either end of the network.
I have loads of stuff written in Max that I rewire in along side my renoise songs live anyway so why not.

coool! will have a bash off this later.

Unfortunately don’t have a Monome to test, but thumbs up just for the effort and for sharing this! :ph34r:

Nevertheless, some hints on how to do the track boundary checks. Also does some more error checks:
[luabox]
– locals & consts

local OscMessage = renoise.Osc.Message
local OscBundle = renoise.Osc.Bundle

local MATRIX_WIDTH = 8 – track count
local MATRIX_HEIGHT = 8 – sequence count


– create the OSC client

client, socket_error = renoise.Socket.create_client(
“localhost”, 8001, renoise.Socket.PROTOCOL_UDP)

if (socket_error) then
app:show_warning(("monome64MaxMSP: Failed to start the " …
“OSC client. Error: ‘%s’”):format(socket_error))
end


– send OSC To Max

– send_matrix_osc

function send_matrix_osc()

if (not socket_error) then
local sequencer = renoise.song().sequencer
local tracks = renoise.song().tracks

local function slot_is_muted(seq_index, track_index)
if (seq_index >= 1 and seq_index <= #sequencer.pattern_sequence) and
(track_index >= 1 and track_index <= #tracks)
then
return sequencer:track_sequence_slot_is_muted(track_index,seq_index)
else
return false
end
end

for seq_index=1,MATRIX_HEIGHT do
for track_index=1,MATRIX_WIDTH do
client:send(
OscMessage("/renoise/song/sequencer/pattern_slot_mutes", {
{tag=“i”, value=track_index},
{tag=“i”, value=seq_index},
{tag=“i”, value=slot_is_muted(track_index, seq_index) and 1 or 0}
})
)
end
end
end
end

– send_mixer_osc

function send_mixer_osc()

if (not socket_error) then
local tracks = renoise.song().tracks

local function track_volume(track_index)
if (track_index >= 1 and track_index <= #tracks) then
return tracks[track_index].prefx_volume.value
else
return 0
end
end

local arguments = table.create()
for track_index=1,MATRIX_WIDTH do
arguments:insert {tag=“f”, value=track_volume(track_index)}
end

client:send(
OscMessage("/renoise/song/tracks/prefx_volume", arguments)
)
end
end


– attach to the renoise song

– attach_to_tracks

function attach_to_tracks()
local tracks = renoise.song().tracks

– attach to new tracks, detach from old ones
for track_index=1,#tracks do
local volume = tracks[track_index].prefx_volume

if (track_index<=MATRIX_WIDTH) then
if (not volume.value_observable:has_notifier(send_mixer_osc)) then
volume.value_observable:add_notifier(send_mixer_osc)
end
else
if (volume.value_observable:has_notifier(send_mixer_osc)) then
volume.value_observable:remove_notifier(send_mixer_osc)
end
end
end

– and immediately update
send_mixer_osc()
end

– attach_to_song

function attach_to_song()
local song = renoise.song()

– sequencer
song.sequencer.pattern_slot_mutes_observable:add_notifier(send_matrix_osc)
send_matrix_osc() – immediately update

– tracks
song.tracks_observable:add_notifier(attach_to_tracks)
attach_to_tracks()
end

– app_new_document_observable -> attach_to_song

renoise.tool().app_new_document_observable:add_notifier(
attach_to_song
)
[/luabox]

awesome, thanks taktik.
testing this now.
now you know why I use max and not lua!

Now you know why I use lua and not max!

Note: the Lua code was written more or less blindly, so it will need some more tweaks here and there.

Work flawlessly. One small change to get the [x y state] arguments in the correct order

[luabox]
function send_matrix_osc()

if (not socket_error) then
local sequencer = renoise.song().sequencer
local tracks = renoise.song().tracks

local function slot_is_muted(track_index, seq_index)
if (seq_index >= 1 and seq_index <= #sequencer.pattern_sequence) and
(track_index >= 1 and track_index <= #tracks)
then
return sequencer:track_sequence_slot_is_muted(track_index,seq_index)
else
return false
end
end

for seq_index=1,MATRIX_HEIGHT do
for track_index=1,MATRIX_WIDTH do
client:send(
OscMessage(“/renoise/song/sequencer/pattern_slot_mutes”, {
{tag=“i”, value=track_index},
{tag=“i”, value=seq_index},
{tag=“i”, value=slot_is_muted(track_index, seq_index) and 1 or 0}
})
)
end
end
end
end
[/luabox]

One small thing I found a bit confusing, but maybe I also didn’t understood the whole thing:
You’re sending “/renoise/song/something” messages from Renoise to Max, which then forwards the stuff to Monome.

Shouldn’t this be “/max/monome_matrix” or something else without the “/renoise” prefix, in order to make clear where the messages go to?

Yes, for completeness you are probably correct.
I will update the renoise tool and max patch later tonight if I have time.

v2 added to 1st post in this thread.