Need help creating a custom osc target

Hey there. I'm currently having fun working on something I called "redirt" - the idea is to expose as much of renoise's OSC API to tidal. I have a few OSC endpoints working, but I'm scratching my head about this one:

:{
let renoise = Target {
        oName="renoise",
        oAddress="127.0.0.1",
        oPort=8000,
        oLatency=0.2,
        oSchedule=Live,
        oWindow=Nothing
        }
    formats = [
        OSC "/renoise/trigger/note_on" $ ArgList [
            ("sound", Just $ VI (-1)),
            ("track", Just $ VI (-1)),
            ("on", Nothing),
            ("velocity", Just $ VI 127)
            ],
        OSC "/renoise/trigger/note_off" $ ArgList [
            ("sound", Just $ VI (-1)),
            ("track", Just $ VI (-1)),
            ("off", Nothing)
            ]
        ]
    sound = pI "sound"
    track = pI "track"
    noteOn = pI "on"
    noteOff = pI "off"
    velocity = pI "velocity"
    vel = velocity
    oscmap = [(renoise, formats)]
:}

renoise has two different endpoints for note_on and note_off. Here, I'm differenciating them with noteOn and noteOff.

d1 $ noteOn "23 42" -- sends note_on events
d2 $ noteOff "23 42" -- sends note_off events

But I don't find it very convenient, I'd rather decouple the note informations and the type of message (on or off). So I tried this:

    formats = [
        OSC "/renoise/trigger/note_{trigger}" $ ArgList [
            ("sound", Just $ VI (-1)),
            ("track", Just $ VI (-1)),
            ("note", Nothing),
            ("velocity", Just $ VI 127)
            ]
        ]
    trigger = pS "trigger"
    sound = pI "sound"
    track = pI "track"
    trigger = pS "trigger"
    velocity = pI "velocity"

Now I can decouple, but ...

d1 $ note "23 42" # trigger "on" -- it works, yay!
d2 $ note "23 42" # trigger "off" -- won't work because of velocity

Here, renoise is rather strict about the endpoint arguments - if note_off receives a velocity, it discards the message.

What are your thoughts? Do you think it is a good idea to decouple "note" and "trigger"? How would you do it considering the constraints?

1 Like

OK, I think I'm on the right track. I decided to stop bothering with note_off messages - I can work around it from the renoise side.

Now, renoise does not understand when I send a (note, octave) message. In order to separate the octave and the note, so far I have to do this:

octave = \p -> note (p * 12)
t1 $ note "1 6 4 7 8 11" |+ octave "<2 3>" # sound "1"

So I'm redefining octave so it produces a note pattern instead, and I combine it with the other note pattern. This is close to tidal + superdirt behaviour but not quite the same.

I'm struggling a bit there - I would like to redefine note so it extracts pattern data from octave and combine it with its own pattern behind the scene. Is there a way to extract pattern data?

Noteon / noteoff doesn't really work with tidal's model, which is fine with overlapping instances of the same note value.. So a good idea to work around that I think.

In your example this is a bit better, without |* you will generate extra events at cycle boundaries in some circumstances:

octave = \p -> note (p |* 12)

There is the extract family of functions, for example extractI "octave" to get a pattern of octave integers from a control pattern. I can't think of a seamless way of using it to get what you want though, in a way that works well with polyphonic patterns.

Thanks a lot for you insights! I shared my code here.

About that note_off thing, that's the conclusion I came to - tidal and renoise are very different in that regard. So far I found ways to mitigate the problem with some instrument parameters on renoise's side. It's not perfect but it does the job.

the extract opens up a lot of things, but now I have to install tidal from git to experiment with it! so far, no luck.