musikinformatik / Steno

Concatenative little metalanguage for live coding
GNU General Public License v2.0
65 stars 7 forks source link

fix fading collectTails-scheme #18

Closed LFSaw closed 7 years ago

LFSaw commented 7 years ago
image

Implementing collectTails scheme (see figure) for replacing Synths (Diff:swapFunc). First row is a "replacement-group" for Filter, 2nd row is a "replacement-group" for Quellen. All Synths are instantiated in the form of the rightmost appearance (called A ) and, when being replaced, get a "replace" message which switches them to the layout in the left versions (called A' resp. A'').

This should allow to use fadeTime and attack to crossfade replacements. a testcase can be found here: https://gist.github.com/LFSaw/aa60234ddb04ae4c5348112ecab170d7

the general scheme of what shoud happen during a fade is shown below:

image
LFSaw commented 7 years ago

@telephon wrote:

OK, here is a formula. Let's suppose that we have a tailBus for all the filter tails, and normally write and read from outBus. All use ReplaceOut.

(
var outbus, tailBus;

// normal = lastSynth, doesn't matter. New synths are always added after, as "normal".
// this works, because it also always writes zero to the tailBus to clean up.

var normal = { |oldSignal, filteredSignal, allTails|

    outbus =  [oldSignal * 0, filteredSignal * 1, allTails * 1].sum; // assuming that tails are cleaned up by last synth.
    tailBus = [oldSignal * 0, filteredSignal * 0, allTails * 0].sum

};

// just fading out differs.

var fadingOutReplacement = { |oldSignal, filteredSignal, allTails|

    outbus =  [oldSignal * 1, filteredSignal * 0, allTails * 0].sum;
    tailBus = [oldSignal * 0, filteredSignal * 1, allTails * 1].sum

};

var fadingOut = { |oldSignal, filteredSignal, allTails|

    outbus =  [oldSignal * 0.5, filteredSignal * 1, allTails * 0].sum; // 0.5 means a fade-in
    tailBus = [oldSignal * 0, filteredSignal * 0, allTails * 0].sum

};
)

Note that when fading out in a filter the input signal is x-faded out (not featured here) so that automatically the filteredSignal should reach silence, even if it is filteredSignal * 1 here.

LFSaw commented 7 years ago

in principle, I'm all up for this, we only need to make sure that dryBus is set also for Quellen...

On 11. Sep 2017, at 18:22, Julian Rohrhuber notifications@github.com wrote:

@telephon commented on this pull request.

In Classes/StenoSignal.sc:

  • signal = XFade2.ar(oldSignal, signal + oldSignal, (mix env) 2 - 1); // can't use Out here, because "in" can be different than "out"
  • FreeSelfWhenDone.kr(env);
  • // collect tails
  • tailSignal,
  • // only add old signal if last in replaceGroup
  • // TODO: if release (not replace), continue mixing
  • oldSignal * gate
  • ]);
  • // assign mix if synth is not released
  • signal = signal * max(mix, 1-gate);

it would be interesting if we could factor out the mix parameter into writeToBus ? Looking from far away, mix is really quite elementary and perhaps should not be up to the signal handling.

Just an idea.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

telephon commented 7 years ago

@LFSaw and, how is things going? Does it work well?

telephon commented 7 years ago

This looks very promising!

LFSaw commented 7 years ago

@telephon, I addressed your comments in 0154321a487961abfdcb5c81766b662fee53024e resp. 93e74f7521076091de82ce3a0d947224fc72ad78

telephon commented 7 years ago

is there anything still missing?

LFSaw commented 7 years ago

@telephon:

is there anything still missing?

I'd appreciate if you could have a look.

I just found out that booting the server after instantiating Steno will result in broken bus allocation since Server:boot calls Server:newAllocators. Took me quite a while to figure out :/

telephon commented 7 years ago

it doesn't compile - are you sure you are working on the right branch? I can fix that, but just want to make sure nothing is wrong.

ERROR: Variable 'feedback' not defined.
  in file '/Volumes/data/sc/quarks/Steno/Classes/Steno.sc'
  line 427 char 74:

                        inB: Limiter.ar(InFeedback.ar(bus, numChannels), 8, 0.01) * feedback.sign,

                        // only do InFeedback for first appearance of variable
-----------------------------------
ERROR: Variable 'feedback' not defined.
  in file '/Volumes/data/sc/quarks/Steno/Classes/Steno.sc'
  line 429 char 20:

                        pan: (feedback.abs * (controls.index < 1) * 2 - 1)

                    );
telephon commented 7 years ago

I'm not sure if this works as expected yet:

t = Steno.new;
s.boot;

// define a few letters
t.quelle(\a, { SinOsc.ar(Rand(200, 2130)) }); // quelle (aka source) produces sound
t.filter(\f, { |input| LFPulse.kr(ExpRand(1, 10), 0, Rand(0.1, 0.5)) * input }); // filter processes sound
t.filter(\g, { |input| CombL.ar(input, 0.2, Rand(0.03, 0.2), 1.3) });
t.fadeTime = 2;

// use them in code:
t.("af");
t.("afg");
t.("aafgafg");
t.("afg");
t.("af");
telephon commented 7 years ago

Btw. I have tried to push some little fixes back to your branch, but somehow this wasn't possible. Maybe you need to activate it?

LFSaw commented 7 years ago

AFAIK, to commonly push changes, we need to set the branch into an organisation that we're both part of.

LFSaw commented 7 years ago
(
// you need to boot the server first (see my comment above)
s.waitForBoot{
    t = Steno.new;

    // define a few letters
    t.quelle(\a, { SinOsc.ar(Rand(200, 2130)) }); // quelle (aka source) produces sound
    t.filter(\f, { |input| LFPulse.kr(ExpRand(1, 10), 0, Rand(0.1, 0.5)) * input }); // filter processes sound
    t.filter(\g, { |input| CombL.ar(input, 0.2, Rand(0.03, 0.2), 1.3) });

}
)

// this only sets fadeout time.
// t.fadeTime = 2;
//use this instead
t.setGlobal(\fadeTime, 2, \attack, 2);
// we should discuss if (a) the differentiation between attack and fadetime is really needed and (b) if these are the right names for the functionality

// use them in code:
t.("af");
t.("afg");
t.("aafgafg");
t.("afg");
t.("af");
telephon commented 7 years ago

we should discuss if (a) the differentiation between attack and fadeTime is really needed and (b) if these are the right names for the functionality

yes.

When I do this:

t.setGlobal(\fadeTime, 4, \attack, 2);
t.("af");
t.("afg");
t.("af");

I hear that fadeTime is not used when a new synth is added (afg). I guess that must have been my own intention? Do we want this?

LFSaw commented 7 years ago

What do you mean by

fadeTime is not kept when a new synth is added

?

fadeTime behaves more like fadeoutTime or decay. AFAI remember, I did not change this behaviour. but maybe we should call it decay, really.

On 19. Oct 2017, at 23:11, Julian Rohrhuber notifications@github.com wrote:

we should discuss if (a) the differentiation between attack and fadetime is really needed and (b) if these are the right names for the functionality

yes.

When I do this:

t.setGlobal(\fadeTime, 4, \attack, 2); t.("af"); t.("afg"); t.("af");

I hear that fadeTime is not kept when a new synth is added. I guess that must have been my own intention? Do we want this?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.

telephon commented 7 years ago

what I meant: setGlobal(\fadeTime, 4) should also create a fade in for a filter?

telephon commented 7 years ago

i think originally this wasn't the case, but we might want it.

LFSaw commented 7 years ago

I'd suggest trying to first merge the branch back into main and then think about changing behaviour...