Popping sound when using crossoverDistortion and PBind

Hi,

Given 2 Synthdefs below. If I play with PBind I am hearing pops at the beginning and end.

Anyone spot the problem ?

Thanks.
eob.

(
SynthDef("crossoverDistortion",
	{
		arg ampl = 0.5, smooth = 0.5, mul = 1.0, busIn = -1, busOut = 0;

		Out.ar(busOut,
			CrossoverDistortion.ar(
                In.ar(busIn),
                ampl,
                smooth,
                mul
			)
		);
	}
).load(s);
)

(
SynthDef("makeASound",
	{
		arg freq = 300, busOut = 0, dur = 1, mul = 1;

		Out.ar(busOut,
			SinOsc.ar(
                freq,0,mul
            );
		);

        FreeSelfWhenDone.kr(EnvGen.kr(Env([1,0], dur), gate: 1));
	}
).load(s);
)

(
~aBus = Bus.audio(s);

~mldy2 = Pbind(
    \instrument, "makeASound",
    \dur, 0.25,
    \degree, Pseq([
        Rest(), Rest(), 0, Rest(),
        2, Rest(), Rest(), Rest(),
    ], 1),
    \mul, 0.1,
    \busOut, ~aBus);

~mldy2 = Pfx(~mldy2, \crossoverDistortion, \busIn, ~aBus);
~play = ~mldy2.play;
)

~play.stop;

Synthesizers generally have an envelope generator controlling an amplifier.

Your makeASound has an envelope :white_check_mark: but it is not controlling an amplifier :x: – so there is no fade in or out. The sound simply starts and stops abruptly. This is likely to cause clicks.

(
SynthDef("makeASound",
    {
        arg freq = 300, busOut = 0, dur = 1, mul = 1;

        // note doneAction:
        // with it, you can delete FreeSelfWhenDone
        var eg = EnvGen.kr(Env([1,0], dur), gate: 1, doneAction: 2);

        Out.ar(busOut,
            SinOsc.ar(
                freq, 0, mul * eg  // <-- amplifier!
             ).dup  // stereo?
        );
    }
).add;
)

Note also that, for pattern usage, it should always be either .add or .store, and generally not .send or .load. It’s documented in the Pattern Guide, subsection “Don’t send or load SynthDefs; use .add or .store instead.” (This usage suggests that you might be using either an old, out-of-date tutorial, or an idiosyncratic one where the author is avoiding standard usages for some reason. Either way, load would cause you problems eventually.)

hjh

Good to know about not using send and load.

Adding the envelope fixed the pop for the example I posted.

I had an envelope when I first noticed this problem but it was in a different synthdef whose output was mapped to an argument in this synthdef. See the example below.

There is still a pop when I use the envelope this way.
Any ideas what could be the issue in this case ?

(
SynthDef(“crossoverDistortion”,
{
arg ampl = 0.5, smooth = 0.5, mul = 1.0, busIn = -1, busOut = 0;

  Out.ar(busOut,
  	CrossoverDistortion.ar(
            In.ar(busIn),
            ampl,
            smooth,
            mul
  	)
  );

}
).add;
)

(
SynthDef(“envelope”,
{
arg dur, busOut = 0;

    var eg = EnvGen.kr(Env([1,0], dur), gate: 1, doneAction: 2);

  Out.kr(busOut, eg);

}
).add;
)

(
SynthDef(“makeASound”,
{
arg freq = 300, busOut = 0, dur = 1, mul = 1, env;

    var out = SinOsc.ar(
            freq, 0, mul * env  // <-- amplifier!
         ).dup; // stereo?

    Out.ar(busOut,
        out
    );

    FreeSelfWhenDone.kr(EnvGen.kr(Env([1,0], dur), gate: 1));
}

).add;
)

(
~cBus = Bus.control(s);
~aBus = Bus.audio(s);

~env = Pbind(
\instrument, “envelope”,
\dur, 0.2,
\degree, Pseq([
Rest(), Rest(), 0, Rest(),
2, Rest(), Rest(), Rest(),
], 1),
\busOut, ~cBus
);

~mldy2 = Pbind(
\instrument, “makeASound”,
\dur, 0.2,
\degree, Pseq([
Rest(), Rest(), 0, Rest(),
2, Rest(), Rest(), Rest(),
], 1),
\busOut, ~aBus,
\env, ~cBus.asMap
);

~mldy2 = Pfx(~mldy2, \crossoverDistortion, \busIn, ~aBus);

~m1 = Ppar([~env, ~mldy2]);

~play = ~m1.play;

)

~play.stop;

I think the Crossover Distortion Ugen just makes a little blip when it starts with silent output - I hear it with Synth(\crossoverDistortion) outside a pattern.

Yes, I think you are right. If I change the pattern to have sounds at the start and end it doesn’t pop.

e.g. 

~mldy2 = Pbind(
    \instrument, "makeASound",
    \dur, 0.2,
    \degree, Pseq([
         1, Rest(), 0, Rest(),
        2, Rest(), Rest(), 2,
    ], 1),
    \busOut, ~aBus,
    \env, ~cBus.asMap
);

It would be nice if there wasn’t this restriction.

I don’t think it’s a restriction – more a matter of proper audio engineering.

A basic principle is that every audio processor needs an envelope.

EVERY time you have an audio processor start or stop abruptly, there is a risk of a click. (You can find people online saying that it’s OK if it happens at a zero crossing, but this is not correct.)

If you don’t want clicks/pops, you must have an envelope. (Yes, that includes effects.)

To apply an effect to an envelope, think of it as a cross fade between the dry and wet signals. When the fx synth starts, it’s outputting the dry signal (so, no discontinuity). Then it fades over to the effect.

(
SynthDef(“crossoverDistortion”,
	{
		arg ampl = 0.5, smooth = 0.5, mul = 1.0, busIn = -1, busOut = 0, gate = 1;
		
		var xfadeEg = EnvGen.kr(Env.asr(0.01, 1, 0.01), gate, doneAction: 2);
		
		XOut.ar(busOut, xfadeEg,
			LeakDC.ar(CrossoverDistortion.ar(
				In.ar(busIn),
				ampl,
				smooth,
				mul
			))
		);
	}
).add;
)

Also, note that I’ve added a LeakDC.ar(...) around the CrossoverDistortion. CrossoverDistortion, given a silent input, outputs 0.25 with default settings. This is DC offset and you usually want to suppress this. LeakDC is the unit to do that.

hjh

PS Please use backtick tags for code:

```
code here
```

The example effect that I just posted will not actually run on your machine – notice that the quote marks have changed into curly, typographic quotes. This is because you formatted your last code example as a quotation, not as a code block.

This works nicely now, thanks for you help.

Just to note: It seems that using either LeakDC or xfade method on their own both remove the pop.
(I do have to increase the attack + release times slightly if I use the envelope on its own.)

I see what you mean about the quotes getting formatted to curly quotes. That would be pretty annoying for someone who is copying code from here. I was able to update my previous small “makeASound” example but I don’t seem to be have the option to edit one before that.