Cabbage Logo
Back to Cabbage Site

Suggestions for envelope UDO truncating synth notes?

Hey everyone! I’m looking for some help/ideas on reaching a goal. I’ve banged my head against this for a little bit already, to no avail… so I feel like I’m missing something either obvious or elegant… maybe even both.

I have a cabbage synth that’s realtime midi controlled. It calls a UDO that returns an A/K rate variable to be used as an ADSR envelope by the synth. The UDO already calls madsr to make an envelope, but I would like to be able to choose a different envelope mode via combobox that will truncates the parent note, basically implementing a sort of “max time” for the envelope’s synth note before it goes straight into the release phase.

A caveat, I know that I could just have the envelope drop to and remain at 0, letting the note continue for whatever duration… but I’d really prefer to terminate processing the note as soon as possible to help maintain as much processing power for real time polyphony as possible.

I have a feeling the answer lies with turnoff2… but I can’t piece it together for some reason. Any help or hints would be huge, thanks!

Just so I’m clear, you want to terminate a note at any time, and in doing so trigger its release phase? I’m not sure how this would work. Here’s an example that uses channels to notify an instrument to turn off. But if if are holding a MIDI note a new note will start anyway? I’m pretty confused, so if my code ticks any of your boxes it’ll be time to crack open the champagne :laughing:

endADSR.csd (1.1 KB)

Thanks for the example Rory! I don’t think it’s quite what I was looking for (or maybe I didn’t understand how to apply it to my problem), but it’s also possible that I’m trying too hard to reach my goal via a specific route and overly complicating the problem in the process. It is definitely helping me to think of alternate methods to get there rather than tunnel-vision focusing on how to reach my goal this one particular way.

Not quite, but sort of… here’s a try at restating the problem: I’m trying to have a UDO that acts as an envelope generator with a mode selected via combobox. If that combobox is set to this second mode, a maximum note length is enforced that is user definable via rslider. Any notes calling this UDO that exceed that max length are turned off and forced to enter the release phase, if they hadn’t already. That way if this envelope UDO were used in a very processing heavy synth, it could cut held notes off after their desired envelope time rather than leaving them processing in silence until the key is released.

For portability, I would like this timing/turnoff processing to happen in the UDO, not the synth itself. If the UDO itself could call turnoff once it’s duration exceeds the value in the rslider, turning off the parent instrument… that would be ideal, and (I think) what I was trying to achieve.

This is a simplified working example, other than the segfault when turnoff condition is reached. This represents the way I’ve been trying to get this working, but perhaps another route would be better. I’ll keep thinking on ideas tonight.

Just in case it behaves different for you, this is being tested on OSX 10.13.6, with csound 6.13. I had issues with changes to string/channel behavior in 6.14, and haven’t had the time to figure out a good solution to that.

endADSR2.csd (1.3 KB)

Hopefully the example helps and this is a little more clear than my first description? Thanks again!

A simple fix is to notify the main instrument that is should turn off, as shown below. I’ll now try to see why that segfault it happening…

opcode MyADSR,ak,0
    iMode  = 2;chnget "mode"
    iMaxTime = 3; chnget "maxtime"
    ; counts 0 to 1 (and beyond!) over duration of "maxtime"
    kTimer linseg 0, iMaxTime, 1
    kEnd = 0;
    iAtt = .1
    iDec = .2
    iSus = .6
    iRel = 1
    aEnv madsr iAtt, iDec, iSus, iRel

    ; once kTimer has been reached "1" and mode is "2", turnoff sounding note
    ; !!! THIS CAUSES SEGFAULT !!!
    if(iMode==2 && kTimer==1) then
        kEnd = 1
    endif

    xout aEnv, kEnd
endop

;instrument will be triggered by keyboard widget
instr 1
    aEnv, kEnd MyADSR
    aOut vco2 p5, p4
    aOut *= aEnv

    if changed(kEnd) ==1 then
        turnoff
    endif
    outs aOut, aOut
endin

Looks like a bug with turnoff. I think the solution above is probably the best option for now.

Yeah, this is pretty similar to where I ended up as a possible workaround too… but since the goal is encapsulation/portability as part of an imported widget group, I’d like to keep the UDO’s usage as short and simple as possible.

I’ll try to design as if it will eventually work as intended, but comment out the segfaults and for now I will look at using a workaround . Should I submit any info about this, or is a bug already open about it etc?

No bug is issues yet. This is the minimal code I was using to demo it:

<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
ksmps = 32
nchnls = 2
0dbfs = 1
opcode MyUDO,a,0
    kTimer linseg 0, 5, 5
    if(kTimer > 1) then
        turnoff
    endif
    xout a(1)
endop
instr 1
    a1 MyUDO
endin
</CsInstruments>
<CsScore>
i1 0 8
</CsScore>
</CsoundSynthesizer>

I don’t have my Csound dev machine set up at the moment, but once I get it up and running I’ll run this through the debugger and see what I can see.

1 Like