I seem to have evidence of DetectSilence receiving 0.0 at its input but failing to end the synth (despite doneAction: 2).
TRACE 3432 swbit2 #units: 22
unit 0 Control
in
out 26 0 0.001
// input into effect is governed by an envelope
// whose gate is closed and is now 0
unit 1 EnvGen
in 0 1 0 1 0 0 2 1 -99 1 0.01 5 -4 0 0.08 5 -4
out 0
unit 2 BinaryOpUGen
in 0 0.001
out 0.001
unit 3 EnvGen
in 0.001 1 0 1 2 0 2 1 -99 1 0 5 -4 0 0.05 5 -4
out 1
unit 4 AudioControl
in
out -0.00126136 -0.00410758
// envelope reduces the signal input to 0
unit 5 BinaryOpUGen
in -0.00126136 0
out 0
unit 6 BinaryOpUGen
in -0.00410758 0
out 0
// bit crushing
unit 7 Control
in
out 2395.44 4.31676
unit 8 Clip
in 4.31676 1 24
out 4.31676
unit 9 BinaryOpUGen
in 1 4.31676
out -3.31676
unit 10 BinaryOpUGen
in 2 -3.31676
out 0.100359
unit 11 Clip
in 2395.44 100 22050
out 2395.44
unit 12 Impulse
in 2395.44 0
out 0
unit 13 Latch
in 0 0
out 0
unit 14 BinaryOpUGen
in 0 0.100359
out 0 -- bit crush result is 0
// DetectSilence input is 0 **but the synth is still running**???
unit 15 DetectSilence
in 0 0.0003 0.1 2
out 0
unit 16 BinaryOpUGen
in 0 1
out 0
unit 17 Latch
in 0 0
out 0
unit 18 BinaryOpUGen
in 0 0.100359
out 0
unit 19 DetectSilence
in 0 0.0003 0.1 2
out 0
unit 20 BinaryOpUGen
in 0 1
out 0
unit 21 Out
in 26 0 0
out
Anyone got any ideas? How is it possible that a flatline 0 input into DetectSilence is somehow not regarded as silent?
The setup is: This is a short-lived effect applied to a signal read from a bus. The duration is controlled by a gate, via Env.asr. I confirmed by dumping server OSC that the gate is being set to zero, and this is confirmed by the node trace, where the second channel of Control (the gate) is 0, as is the envelope, as are the signal * envelope units.
It’s (signal * envelope) --> effect --> DetectSilence and output because the effect might ring (as in a resonator bank, or comb filter, or…). Upon release, the source going into the effect should be zeroed, and the effect itself should decay to 0. (In the bit crusher, the decay to 0 is instantaneous.) At that point, DetectSilence should knock out the synth.
In the testing scenario, I run a pattern until I notice stuck nodes. Then I stop the pattern and manually do a s.sendMsg(\n_trace, the_node_ID) – it takes a few seconds to find the note ID in the server tree dump and type it into that statement, so I’m quite sure the 0 is there for at least several seconds.
Another observation: In another test that I ran just now, a 61-ms note got stuck, while a 60-ms note cut off correctly. So it isn’t the case that shorter notes always fail – short notes are at worst indeterminate.
Hmm… In a bit crusher, using the formula sig.round(someFactor) where the factor is based on the desired bit depth, if sig stays below half the factor, then the round result will always be zero. If DetectSilence requires its input to be nonzero for a short duration before executing any doneAction, then a short note with a quiet input would get stuck.
In that case, I could just add a short Trig1 or something to the DetectSilence input, to force a nonzero input.
Didn’t think of that earlier, but I bet that’s it.
Perhaps it might be worth adding an extra argument to it with two optional timeout parameters? One for total time and one for time after sound detected?
Actually it’s a tricky requirement – I don’t want to hold the synth open for an unnecessarily long time, but the Trig1 approach could still choke a note off early if it happens to get a below-threshold input for the bit crusher. Maybe I just accept that (since I probably won’t use that one all the time), or maybe try to ensure a minimum volume. Not a high priority at this time, though.