Sonic-pi: Feature request: MIDI "synth"

Created on 11 Mar 2019  路  7Comments  路  Source: sonic-pi-net/sonic-pi

I'm not sure if this is feasible or not, but it would be nice to have a "synth" that instead of synthesising notes, would just send them as MIDI signals.
This would make it really easy to adapt a piece to use an external synth by just wrapping it in a with_synth :midi do block.
Currently the only way to do that is to go through the code replacing calls to play with midi, and when you have things like play_pattern_timed it starts getting complicated.

Feature Request language

All 7 comments

Interesting idea.

How would you go about handling the subtle but significant difference with how synth and midi both handle envelopes. midi only supports the sustain: opt, whereas with synth it's typical to use the release: opt for a similar purpose.

Perhaps midi should treat sustain: and release: similarly and in the presence of both favour sustain:?

To be honest I hadn't thought through in detail how the differences would be handled, but ideally "normal" usage should just work with both standard synths and midi.

My initial idea would be to set the midi sustain: to the total duration of the note (i.e. :attack + :decay + :sustain + :release). Are there any cases that wouldn't work with that?

My initial idea would be to set the midi sustain: to the total duration of the note (i.e. :attack + :decay + :sustain + :release). Are there any cases that wouldn't work with that?

Excellent idea. Seems like it would work well on first thought. Let me think about it a bit deeper...

Great!
Another thing I just thought of: it would also need a way of converting play's amp: to midi's vel:. Maybe a simple scaling factor with min/max clamping would do? Or otherwise it could be a unary function. I imagine it would be an option on the :midi synth with a reasonable default.

I've been thinking about this a bit, and realised that there might be other scenarios where a user wants to create a custom synth that does something other than the usual forwarding to supercollider, such as using a set of samples as an instrument (e.g. here, and I think @rbnpi has done something similar too). It would be great if there was a way to make these work with the standard play* commands instead of having to use custom functions.

What about having something like the following, where defsynth would define a new named synth that calls the code block with all the params for every note played?

# define a new synth called :midi that forwards all notes to the midi command
defsynth :midi do |note, amp=1, attack=0, decay=0, sustain=0, release=0|
  v = (amp * 32).min(0).max(127) # map 0 - 4-ish range onto 0 - 127
  sus = attack + decay + sustain + release
  midi note, vel: v, sustain: sus
end

# now :midi is available as a synth
with_synth :midi do
  play_pattern_timed [60, 68, 76, 82, 84], [0.5, 1], amp: 2
end

Yes! I've been thinking about this for a while too. I think that the defsynth should also implicitly put all computation within a thread, so any calls to sleep won't affect the code which triggers it (it should only temporally affect the specific synth).

Just adding a gentle ping to make sure this doesn't get forgotten @samaaron

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AlexandreRangel picture AlexandreRangel  路  7Comments

emlyn picture emlyn  路  4Comments

sbeaumont picture sbeaumont  路  3Comments

ostephagus picture ostephagus  路  4Comments

datramt picture datramt  路  5Comments