Synth Tutorial

von HAL


Grundlegende Wellenformen:


Additative Synthese

Der Modulator moduliert die Tonhöhe des Oszillators (Vibrato):

Modulator -> Oscillator -> Verstärker -> Output


Subtraktive Synthese

Der (volle) Klang des Oszillators wird durch einen Filter geleitet
(um die Klangfülle zu reduzieren):

Oszillator -> Filter -> Verstärker -> Output


ADSR Hüllkurve

1.) Die Lautstärke wächst von 0% auf 100% in x Sekunden
    ("attack time").
2.) Die Lautstärke fällt von 100% auf xx% in y Sekunden
    (x = "sustain level", y = "decay time").
3.) Die Laustärke verbleibt bei auf dem Sustain-Level,
    bis ein "key off" erfolgt
4.) Die Lautstärke fällt auf 0% in x Sekunden
    ("release time").



Filter

Lowpass:
- löscht alle Frequenzen überhalb der "CutOff-Frequenz"

Highpass:
- löscht alle Frequenzen unterhalb der "CutOff-Frequenz"

BandPass:
- lässt nur Frequenzen eines bestimmten Frequenzbereichs durch

Notch:
- löscht eine bestimmte Frequenz

Einige Filter besitzen noch einen Parameter namens "Resonanz", der angibt wie stark die Frequenzen um die "CutOff-Frequenz" herum verstärkt werden.


Hier die wichtigsten Funktionen zum Berechnen der Koeffizienten für IIR-Filter:
// omega & bandwidth = 0 - pi (pi ~ output freq / 2)
//


#define LN2O2 0.34657359027997265470861606072909

/*
usage:

y[n] = a0 * x[n] + a1 * x[n-1] + a2 * x[n-2] +
                   b1 * y[n-1] + b2 * y[n-2]
*/

typedef struct {
	double a0, a1, a2,
		       b1, b2;
} biquad_coeff_t;


// lowpass
void
biquad_lp(biquad_coeff_t *biquad, float32 omega, float32 bandwidth)
{
	float64 sn, cs, al, a0, a1, a2, b0, b1, b2, ooa0;

	sn = sin(omega);
	cs = cos(omega);
	al = sn * sinh(LN2O2 * bandwidth * omega / sn);

	b0 = (1 - cs) * 0.5;
	b1 = 1 - cs;
	b2 = (1 - cs) * 0.5;
	a0 = 1 + al;
	a1 = -2 * cs;
	a2 = 1 - al;

	ooa0 = 1.0f / a0;

	biquad->a0 = b0 * ooa0;
	biquad->a1 = b1 * ooa0;
	biquad->a2 = b2 * ooa0;
	biquad->b1 = -a1 * ooa0;
	biquad->b2 = -a2 * ooa0;
}

// bandpass
void
biquad_bp(biquad_coeff_t *biquad, float32 omega, float32 bandwidth)
{
	float64 sn, cs, al, a0, a1, a2, b0, b1, b2, ooa0;

	sn = sin(omega);
	cs = cos(omega);
	al = sn * sinh(LN2O2 * bandwidth * omega / sn);

	b0 = al;
	b1 = 0;
	b2 = -al;
	a0 = 1 + al;
	a1 = -2 * cs;
	a2 = 1 - al;

	ooa0 = 1.0f / a0;

	biquad->a0 = b0 * ooa0;
	biquad->a1 = b1 * ooa0;
	biquad->a2 = b2 * ooa0;
	biquad->b1 = -a1 * ooa0;
	biquad->b2 = -a2 * ooa0;
}

// highpass
void
biquad_hp(biquad_coeff_t *biquad, float32 omega, float32 bandwidth)
{
	float64 sn, cs, al, a0, a1, a2, b0, b1, b2, ooa0;

	sn = sin(omega);
	cs = cos(omega);
	al = sn * sinh(LN2O2 * bandwidth * omega / sn);

	b0 = (1 + cs) * 0.5;
	b1 = -(1 + cs);
	b2 = (1 + cs) * 0.5;
	a0 = 1 + al;
	a1 = -2 * cs;
	a2 = 1 - al;

	ooa0 = 1.0f / a0;

	biquad->a0 = b0 * ooa0;
	biquad->a1 = b1 * ooa0;
	biquad->a2 = b2 * ooa0;
	biquad->b1 = -a1 * ooa0;
	biquad->b2 = -a2 * ooa0;
}

// notch
void
biquad_no(biquad_coeff_t *biquad, float32 omega, float32 bandwidth)
{
	float64 sn, cs, al, a0, a1, a2, b0, b1, b2, ooa0;

	sn = sin(omega);
	cs = cos(omega);
	al = sn * sinh(LN2O2 * bandwidth * omega / sn);

	b0 = 1;
	b1 = -2 * cs;
	b2 = 1;
	a0 = 1 + al;
	a1 = b1;
	a2 = 1 - al;

	ooa0 = 1.0f / a0;

	biquad->a0 = b0 * ooa0;
	biquad->a1 = b1 * ooa0;
	biquad->a2 = b2 * ooa0;
	biquad->b1 = -a1 * ooa0;
	biquad->b2 = -a2 * ooa0;
}

// peaking equalizer
void
biquad_peq(biquad_coeff_t *biquad, float32 omega, float32 bandwidth, float32 dbgain)
{
	float64 sn, cs, al, a, a0, a1, a2, b0, b1, b2, ooa, ooa0;

	sn = sin(omega);
	cs = cos(omega);
	a  = pow(10, dbgain * 0.025);
	ooa = 1.0 / a;
	al = sn * sinh(LN2O2 * bandwidth * omega / sn);

	b0 = 1 + al * a;
	b1 = -2 * cs;
	b2 = 1 - al * a;
	a0 = 1 + al * ooa;
	a1 = b1;
	a2 = 1 - al * ooa;

	ooa0 = 1.0f / a0;

	biquad->a0 = b0 * ooa0;
	biquad->a1 = b1 * ooa0;
	biquad->a2 = b2 * ooa0;
	biquad->b1 = -a1 * ooa0;
	biquad->b2 = -a2 * ooa0;
}

// low shelf
void
biquad_ls(biquad_coeff_t *biquad, float32 omega, float32 dbgain, float32 slope)
{
	float64 sn, cs, be, a, a0, a1, a2, b0, b1, b2, ooa0, ap1, am1;

	sn  = sin(omega);
	cs  = cos(omega);
	a   = pow(10, dbgain * 0.025);
	ap1 = a + 1;
	am1 = a - 1;
	be  = sqrt((a * a + 1) / slope - am1 * am1);

	b0 = a * (ap1 - am1 * cs + be * sn);
	b1 = 2* a * (am1 - ap1 * cs);
	b2 = a * (ap1 - am1 * cs - be * sn);
	a0 = ap1 + am1 * cs + be * sn;
	a1 = -2 * (am1 + ap1 * cs);
	a2 = ap1 + am1 * cs - be * sn;

	ooa0 = 1.0f / a0;

	biquad->a0 = b0 * ooa0;
	biquad->a1 = b1 * ooa0;
	biquad->a2 = b2 * ooa0;
	biquad->b1 = -a1 * ooa0;
	biquad->b2 = -a2 * ooa0;
}

// high shelf
void
biquad_hs(biquad_coeff_t *biquad, float32 omega, float32 dbgain, float32 slope)
{
	float64 sn, cs, be, a, a0, a1, a2, b0, b1, b2, ooa0, ap1, am1;

	sn  = sin(omega);
	cs  = cos(omega);
	a   = pow(10, dbgain * 0.025);
	ap1 = a + 1;
	am1 = a - 1;
	be  = sqrt((a * a + 1) / slope - am1 * am1);

	b0 = a * (ap1 + am1 * cs + be * sn);
	b1 = -2 * a * (am1 + ap1 * cs);
	b2 = a * (ap1 + am1 * cs - be * sn);
	a0 = ap1 - am1 * cs + be * sn;
	a1 = 2 * (am1 - ap1 * cs);
	a2 = ap1 - am1 * cs - be * sn;

	ooa0 = 1.0f / a0;

	biquad->a0 = b0 * ooa0;
	biquad->a1 = b1 * ooa0;
	biquad->a2 = b2 * ooa0;
	biquad->b1 = -a1 * ooa0;
	biquad->b2 = -a2 * ooa0;
}


Beispielaufbau eines Oszillatorblocks

Folgendes benutze ich zur Zeit (mehr oder weniger):

        LFO-->ENV---\
                     \
  LFO-->OSC-->BIQUAD--*-->DISTORT---\
                                    |
        LFO-->ENV---\               |
                     \              |
  LFO-->OSC-->BIQUAD--*-->DISTORT---+
                                    |
        LFO-->ENV---\               |
                     \              |
  LFO-->OSC-->BIQUAD--*-->DISTORT---+
                                    |
        LFO-->ENV---\               |
                     \              |
  LFO-->OSC-->BIQUAD--*-->DISTORT---+->CHORUS/ECHO/REVERB

LFO     = low frequency oscillator
ENV     = adsr envelope
DISTORT = a distortion function


Was jetzt?

1.] Beweg' deinen Hintern zu www.harmonic-central.com
     und folge allen weiteren Links.

2.] Gehe zu www.maz-sound.com
     und downloade so viele Synthesizer wie möglich.

3.] Schau dir die mitgelieferten Sourcen an. (synth-demo.zip).

4.] ...
    EXPERIMENTIERE!!!
    EXPERIMENTIERE!!!
    EXPERIMENTIERE!!!


Okay, that's all.......

Bei Fragen, Mail an bschoedlbauer@gmx.net.


(Hal)