Main Archive Specials IRC Wiki | FAQ Links Submit Forum
Search

Analysis

Effects

Filters

Other

Synthesis

All

Entries in this category

2 Wave shaping things
Alien Wah
Bit quantization/reduction effect
Class for waveguide/delay effects
Compressor
Decimator
Delay time calculation for reverberation
Early echo's with image-mirror technique
ECE320 project: Reverberation w/ parameter control from PC
Guitar feedback
Lo-Fi Crusher
Most simple and smooth feedback delay
Most simple static delay
Parallel combs delay calculation
Phaser code
Reverberation Algorithms in Matlab
Reverberation techniques
smsPitchScale Source Code
Soft saturation
Stereo Enhancer
Time compression-expansion using standard phase vocoder
transistor differential amplifier simulation
Variable-hardness clipping function
WaveShaper
Waveshaper
Waveshaper
Waveshaper (simple description)
Waveshaper :: Gloubi-boulga

2 Wave shaping things

References : Posted by Frederic Petrot

Notes :
Makes nice saturations effects that can be easilly computed using cordic
First using a atan function:
y1 using k=16
max is the max value you can reach (32767 would be a good guess)
Harmonics scale down linealy and not that fast

Second using the hyperbolic tangent function:
y2 using k=2
Harmonics scale down linealy very fast


Code :
y1 = (max>>1) * atan(k * x/max)

y2 = max * th(x/max)


no comments on this item | add a comment | nofrills version


Alien Wah

References : Nasca Octavian Paul ( paulnasca[AT]email.ro )
Linked file : alienwah.c

Notes :
"I found this algoritm by "playing around" with complex numbers. Please email me your opinions about it.

Paul."




2 comment(s) | add a comment | nofrills version


Bit quantization/reduction effect

Type : Bit-level noise-generating effect
References : Posted by Jon Watte

Notes :
This function, run on each sample, will emulate half the effect of running your signal through a Speak-N-Spell or similar low-bit-depth circuitry.

The other half would come from downsampling with no aliasing control, i e replicating every N-th sample N times in the output signal.


Code :
short keep_bits_from_16( short input, int keepBits ) {
  return (input & (-1 << (16-keepBits)));
}



no comments on this item | add a comment | nofrills version


Class for waveguide/delay effects

Type : IIR filter
References : Posted by arguru[AT]smartelectronix.com

Notes :
Flexible-time, non-sample quantized delay , can be used for stuff like waveguide synthesis or time-based (chorus/flanger) fx.

MAX_WG_DELAY is a constant determining MAX buffer size (in samples)


Code :
class cwaveguide  
{
public:
    cwaveguide(){clear();}
    virtual ~cwaveguide(){};
    
    void clear()
    {
        counter=0;
        for(int s=0;s<MAX_WG_DELAY;s++)
            buffer[s]=0;
    }
    
    inline float feed(float const in,float const feedback,double const delay)
    {
        // calculate delay offset
        double back=(double)counter-delay;
        
        // clip lookback buffer-bound
        if(back<0.0)
            back=MAX_WG_DELAY+back;
        
        // compute interpolation left-floor
        int const index0=floor_int(back);
        
        // compute interpolation right-floor
        int index_1=index0-1;
        int index1=index0+1;
        int index2=index0+2;
        
        // clip interp. buffer-bound
        if(index_1<0)index_1=MAX_WG_DELAY-1;
        if(index1>=MAX_WG_DELAY)index1=0;
        if(index2>=MAX_WG_DELAY)index2=0;
        
        // get neighbourgh samples
        float const y_1= buffer [index_1];
        float const y0 = buffer [index0];
        float const y1 = buffer [index1];
        float const y2 = buffer [index2];
        
        // compute interpolation x
        float const x=(float)back-(float)index0;
        
        // calculate
        float const c0 = y0;
        float const c1 = 0.5f*(y1-y_1);
        float const c2 = y_1 - 2.5f*y0 + 2.0f*y1 - 0.5f*y2;
        float const c3 = 0.5f*(y2-y_1) + 1.5f*(y0-y1);
        
        float const output=((c3*x+c2)*x+c1)*x+c0;
        
        // add to delay buffer
        buffer[counter]=in+output*feedback;
        
        // increment delay counter
        counter++;
        
        // clip delay counter
        if(counter>=MAX_WG_DELAY)
            counter=0;
        
        // return output
        return output;
    }
    
    float    buffer[MAX_WG_DELAY];
    int        counter;
};


no comments on this item | add a comment | nofrills version


Compressor

Type : Hardknee compressor with RMS look-ahead envelope calculation and adjustable attack/decay
References : Posted by flashinc[AT]mail[DOT]ru

Notes :
RMS is a true way to estimate _musical_ signal energy,
our ears behaves in a same way.

to making all it work,
try this values (as is, routine accepts percents and milliseconds) for first time:

threshold = 50%
slope = 50%
RMS window width = 1 ms
lookahead = 3 ms
attack time = 0.1 ms
release time = 300 ms

This code can be significantly improved in speed by
changing RMS calculation loop to 'running summ'
(keeping the summ in 'window' -
adding next newest sample and subtracting oldest on each step)


Code :
void compress
    (
        float*  wav_in,     // signal
        int     n,          // N samples
        double  threshold,  // threshold (percents)
        double  slope,      // slope angle (percents)
        int     sr,         // sample rate (smp/sec)
        double  tla,        // lookahead  (ms)
        double  twnd,       // window time (ms)
        double  tatt,       // attack time  (ms)
        double  trel        // release time (ms)
    )
{
    typedef float   stereodata[2];
    stereodata*     wav = (stereodata*) wav_in; // our stereo signal
    threshold *= 0.01;          // threshold to unity (0...1)
    slope *= 0.01;              // slope to unity
    tla *= 1e-3;                // lookahead time to seconds
    twnd *= 1e-3;               // window time to seconds
    tatt *= 1e-3;               // attack time to seconds
    trel *= 1e-3;               // release time to seconds

    // attack and release "per sample decay"
    double  att = (tatt == 0.0) ? (0.0) : exp (-1.0 / (sr * tatt));
    double  rel = (trel == 0.0) ? (0.0) : exp (-1.0 / (sr * trel));

    // envelope
    double  env = 0.0;

    // sample offset to lookahead wnd start
    int     lhsmp = (int) (sr * tla);

    // samples count in lookahead window
    int     nrms = (int) (sr * twnd);

    // for each sample...
    for (int i = 0; i < n; ++i)
    {
        // now compute RMS
        double  summ = 0;

        // for each sample in window
        for (int j = 0; j < nrms; ++j)
        {
            int     lki = i + j + lhsmp;
            double  smp;

            // if we in bounds of signal?
            // if so, convert to mono
            if (lki < n)
                smp = 0.5 * wav[lki][0] + 0.5 * wav[lki][1];
            else
                smp = 0.0;      // if we out of bounds we just get zero in smp

            summ += smp * smp;  // square em..
        }

        double  rms = sqrt (summ / nrms);   // root-mean-square

        // dynamic selection: attack or release?
        double  theta = rms > env ? att : rel;

        // smoothing with capacitor, envelope extraction...
        // here be aware of pIV denormal numbers glitch
        env = (1.0 - theta) * rms + theta * env;

        // the very easy hard knee 1:N compressor
        double  gain = 1.0;
        if (env > threshold)
            gain = gain - (env - threshold) * slope;

        // result - two hard kneed compressed channels...
        float  leftchannel = wav[i][0] * gain;
        float  rightchannel = wav[i][1] * gain;
    }
}


2 comment(s) | add a comment | nofrills version


Decimator

Type : Bit-reducer and sample&hold unit
References : Posted by tobyear[AT]web[DOT]de

Notes :
This is a simple bit and sample rate reduction code, maybe some of you can use it. The parameters are bits (1..32) and rate (0..1, 1 is the original samplerate).
Call the function like this:
y=decimate(x);

A VST plugin implementing this algorithm (with full Delphi source code included) can be downloaded from here:
http://tobybear.phreque.com/decimator.zip

Comments/suggestions/improvements are welcome, send them to: tobybear@web.de


Code :
// bits: 1..32
// rate: 0..1 (1 is original samplerate)

********** Pascal source **********
var m:longint;
    y,cnt,rate:single;

// call this at least once before calling
// decimate() the first time
procedure setparams(bits:integer;shrate:single);
begin
m:=1 shl (bits-1);
cnt:=1;
rate:=shrate;
end;

function decimate(i:single):single;
begin
cnt:=cnt+rate;
if (cnt>1) then
begin
  cnt:=cnt-1;
  y:=round(i*m)/m;
end;
result:=y;
end;

********** C source **********
int bits=16;
float rate=0.5;

long int m=1<<(bits-1);
float y=0,cnt=0;

float decimate(float i)
{
cnt+=rate;
if (cnt>=1)
{
  cnt-=1;
  y=(long int)(i*m)/(float)m;
}
return y;
}


3 comment(s) | add a comment | nofrills version


Delay time calculation for reverberation

References : Posted by Andy Mucho

Notes :
This is from some notes I had scribbled down from a while back on
automatically calculating diffuse delays. Given an intial delay line gain
and time, calculate the times and feedback gain for numlines delay lines..


Code :
int   numlines = 8;
float t1 = 50.0;        // d0 time
float g1 = 0.75;        // d0 gain
float rev = -3*t1 / log10 (g1);

for (int n = 0; n < numlines; ++n)
{
  float dt = t1 / pow (2, (float (n) / numlines));
  float g = pow (10, -((3*dt) / rev));
  printf ("d%d t=%.3f g=%.3f\n", n, dt, g);
}

The above with t1=50.0 and g1=0.75 yields:

d0 t=50.000 g=0.750
d1 t=45.850 g=0.768
d2 t=42.045 g=0.785
d3 t=38.555 g=0.801
d4 t=35.355 g=0.816
d5 t=32.421 g=0.830
d6 t=29.730 g=0.843
d7 t=27.263 g=0.855

To go more diffuse, chuck in dual feedback paths with a one cycle delay
effectively creating a phase-shifter in the feedback path, then things get
more exciting.. Though what the optimum phase shifts would be I couldn't
tell you right now..


1 comment(s) | add a comment | nofrills version


Early echo's with image-mirror technique

References : Donald Schulz
Linked file : early_echo.c
Linked file : early_echo_eng.c

Notes :
(see linked files)
Donald Schulz's code for computing early echoes using the image-mirror method. There's an english and a german version.




no comments on this item | add a comment | nofrills version


ECE320 project: Reverberation w/ parameter control from PC

References : Posted by Brahim Hamadicharef (project by Hua Zheng and Shobhit Jain)
Linked file : rev.txt

Notes :
rev.asm
ECE320 project: Reverberation w/ parameter control from PC
Hua Zheng and Shobhit Jain
12/02/98 ~ 12/11/98
(se linked file)




no comments on this item | add a comment | nofrills version


Guitar feedback

References : Posted by Sean Costello

Notes :
It is fairly simple to simulate guitar feedback with a simple Karplus-Strong algorithm (this was described in a CMJ article in the early 90's):



Code :
Run the output of the Karplus-Strong delay lines into a nonlinear shaping function for distortion (i.e. 6 parallel delay lines for 6 strings, going into 1 nonlinear shaping function that simulates an overdriven amplifier, fuzzbox, etc.);

Run part of the output into a delay line, to simulate the distance from the amplifier to the "strings";

The delay line feeds back into the Karplus-Strong delay lines. By controlling the amount of the output fed into the delay line, and the length of the delay line, you can control the intensity and pitch of the feedback note.


3 comment(s) | add a comment | nofrills version


Lo-Fi Crusher

Type : Quantizer / Decimator with smooth control
References : Posted by David Lowenfels

Notes :
Yet another bitcrusher algorithm. But this one has smooth parameter control.

Normfreq goes from 0 to 1.0; (freq/samplerate)
Input is assumed to be between 0 and 1.
Output gain is greater than unity when bits < 1.0;


Code :
function output = crusher( input, normfreq, bits );
    step = 1/2^(bits);
    phasor = 0;
    last = 0;

    for i = 1:length(input)
       phasor = phasor + normfreq;
       if (phasor >= 1.0)
          phasor = phasor - 1.0;
          last = step * floor( input(i)/step + 0.5 ); %quantize
       end
       output(i) = last; %sample and hold
    end
end


1 comment(s) | add a comment | nofrills version


Most simple and smooth feedback delay

Type : Feedback delay
References : Posted by antiprosynthesis[AT]hotmail[DOT]com

Notes :
fDlyTime = delay time parameter (0-1)

i = input index
j = delay index


Code :
if( i >= SampleRate )
    i = 0;

j = i - (fDlyTime * SampleRate);

if( j < 0 )
    j += SampleRate;

Output = DlyBuffer[ i++ ] = Input + (DlyBuffer[ j ] * fFeedback);


2 comment(s) | add a comment | nofrills version


Most simple static delay

Type : Static delay
References : Posted by antiprosynthesis[AT]hotmail[DOT]com

Notes :
This is the most simple static delay (just delays the input sound an amount of samples). Very useful for newbies also probably very easy to change in a feedback delay (for comb filters for example).

Note: fDlyTime is the delay time parameter (0 to 1)

i = input index
j = output index


Code :
if( i >= SampleRate )
    i = 0;

DlyBuffer[ i ] = Input;

j = i - (fDlyTime * SampleRate);

i++;

if( j < 0 )
    j = SampleRate + j;

Output = DlyBuffer[ j ];


3 comment(s) | add a comment | nofrills version


Parallel combs delay calculation

References : Posted by Juhana Sadeharju ( kouhia[AT]nic[DOT]funet[DOT]fi )

Notes :
This formula can be found from a patent related to parallel combs structure. The formula places the first echoes coming out of parallel combs to uniformly distributed sequence. If T_ ,...,T_n are the delay lines in increasing order, the formula can be derived by setting T_(k-1)/T_k = Constant and T_n/(2*T_1) = Constant, where 2*T_1 is the echo coming just after the echo T_n.
I figured this out myself as it is not told in the patent. The formula is not the best which one can come up. I use a search method to find echo sequences which are uniform enough for long enough time. The formula is uniform for a short time only.
The formula doesn't work good for series allpass and FDN structures, for which a similar formula can be derived with the same idea. The search method works for these structures as well.




no comments on this item | add a comment | nofrills version


Phaser code

References : Posted by Ross Bencina
Linked file : phaser.cpp

Notes :
(see linked file)



3 comment(s) | add a comment | nofrills version


Reverberation Algorithms in Matlab

References : Posted by Gautham J. Mysore (gauthamjm [AT] yahoo [DOT] com)
Linked file : MATLABReverb.zip

Notes :
These M-files implement a few reverberation algorithms (based on Schroeder's and Moorer's algorithms). Each of the M-files include a short description.

There are 5 M-files that implement reverberation. They are:

- schroeder1.m
- schroeder2.m
- schroeder3.m
- moorer.m
- stereoverb.m

The remaining 8 M-files implement filters, delay lines etc. Most of these are used in the above M-files. They can also be used as building blocks for other reverberation algorithms.




3 comment(s) | add a comment | nofrills version


Reverberation techniques

References : Posted by Sean Costello

Notes :
* Parallel comb filters, followed by series allpass filters. This was the original design by Schroeder, and was extended by Moorer. Has a VERY metallic sound for sharp transients.

* Several allpass filters in serie (also proposed by Schroeder). Also suffers from metallic sound.

* 2nd-order comb and allpass filters (described by Moorer). Not supposed to give much of an advantage over first order sections.

* Nested allpass filters, where an allpass filter will replace the delay line in another allpass filter. Pioneered by Gardner. Haven't heard the results.

* Strange allpass amp delay line based structure in Jon Dattorro article (JAES). Four allpass filters are used as an input to a cool "figure-8" feedback loop, where four allpass reverberators are used in series with
a few delay lines. Outputs derived from various taps in structure. Supposedly based on a Lexicon reverb design. Modulating delay lines are used in some of the allpass structures to "spread out" the eigentones.

* Feedback Delay Networks. Pioneered by Puckette/Stautner, with Jot conducting extensive recent research. Sound VERY good, based on initial experiments. Modulating delay lines and feedback matrixes used to spread out eigentones.

* Waveguide-based reverbs, where the reverb structure is based upon the junction of many waveguides. Julius Smith developed these. Recently, these have been shown to be essentially equivalent to the feedback delay network reverbs. Also sound very nice. Modulating delay lines and scattering values used to spread out eigentones.

* Convolution-based reverbs, where the sound to be reverbed is convolved with the impulse response of a room, or with exponentially-decaying white noise. Supposedly the best sound, but very computationally expensive, and not very flexible.

* FIR-based reverbs. Essentially the same as convolution. Probably not used, but shorter FIR filters are probably used in combination with many of the above techniques, to provide early reflections.




no comments on this item | add a comment | nofrills version


smsPitchScale Source Code

Type : Pitch Scaling (often incorrectly referred to as "Pitch Shifting") using the Fourier transform
References : Posted by sms[AT]dspdimension.com
Linked file : http://www.dspdimension.com
Code :
See above web site

1 comment(s) | add a comment | nofrills version


Soft saturation

Type : waveshaper
References : Posted by Bram de Jong

Notes :
This only works for positive values of x. a should be in the range 0..1

Code :
x < a:
  f(x) = x
x > a:
  f(x) = a + (x-a)/(1+((x-a)/(1-a))^2)
x > 1:
  f(x) = (a+1)/2


no comments on this item | add a comment | nofrills version


Stereo Enhancer

References : Posted by kurmisk[at]inbox[DOT]lv

Notes :

Stereo Enhanca


Code :

// WideCoeff  0.0 .... 1.5

#define StereoEnhanca(SamplL,SamplR,MonoSign, \
  DeltaLeft,WideCoeff ) \
  MonoSign = (SamplL + SamplR)/2.0; \
  DeltaLeft = SamplL - MonoSign; \
  DeltaLeft = DeltaLeft * WideCoeff; \
  SamplL=SamplL + DeltaLeft; \
  SamplR=SamplR - DeltaLeft;  


3 comment(s) | add a comment | nofrills version


Time compression-expansion using standard phase vocoder

Type : vocoder phase time stretching
References : Posted by Cournape
Linked file : vocoder.m

Notes :
Standard phase vocoder. For imporved techniques ( faster ), see paper of Laroche : "Improved phase vocoder time-scale modification of audio"
Laroche, J.; Dolson, M.
Speech and Audio Processing, IEEE Transactions on , Volume: 7 Issue: 3 , May 1999
Page(s): 323 -332




7 comment(s) | add a comment | nofrills version


transistor differential amplifier simulation

Type : Waveshaper
References : Posted by Christian[at]savioursofsoul[dot]de

Notes :
Writting an exam about electronic components, i learned several equations about simulating that stuff. One simplified equation was the tanh(x) formula for the differential amplifier. It is not exact, but since the amplifiers are driven with only small amplitudes the behaviour is most often even advanced linear.
The fact, that the amp is differential, means, that the 2n order is eliminated, so the sound is also similar to a tube.
For a very fast use, this code is in pure assembly language (not optimized with SSE-Code yet) and performs in VST-Plugins very fast.
The code was written in delphi and if you want to translate the assembly code, you should know, the the parameters passing is done via registers. So pinp=EAX pout=EDX sf=ECX.


Code :
procedure Transistor(pinp,pout : PSingle; sf:Integer; Faktor: Single);
asm
fld Faktor
@Start:
fld [eax].single
fmul st(0),st(1)

fldl2e
fmul
fld st(0)
frndint
fsub st(1),st
fxch st(1)
f2xm1
fld1
fadd
fscale     { result := z * 2**i }
fstp st(1)

fld st(0)
fmulp

fld st(0)
fld1
faddp
fld1
fsubp st(2),st(0)
fdivp

fstp [edx].single

add eax,4
add edx,4
loop    @Start
fstp st(0)
end;


no comments on this item | add a comment | nofrills version


Variable-hardness clipping function

References : Posted by Laurent de Soras
Linked file : laurent.gif

Notes :
k >= 1 is the "clipping hardness". 1 gives a smooth clipping, and a high value gives hardclipping.

Don't set k too high, because the formula use the pow() function, which use exp() and would overflow easily. 100 seems to be a reasonable value for "hardclipping"


Code :
f (x) = sign (x) * pow (atan (pow (abs (x), k)), (1 / k));


4 comment(s) | add a comment | nofrills version


WaveShaper

Type : waveshaper
References : Posted by Bram de Jong

Notes :
where x (in [-1..1] will be distorted and a is a distortion parameter that goes from 1 to infinity
The equation is valid for positive and negativ values.
If a is 1, it results in a slight distortion and with bigger a's the signal get's more funky.

A good thing about the shaper is that feeding it with bigger-than-one
values, doesn't create strange fx. The maximum this function will reach is
1.2 for a=1.


Code :
f(x,a) = x*(abs(x) + a)/(x^2 + (a-1)*abs(x) + 1)

no comments on this item | add a comment | nofrills version


Waveshaper

Type : waveshaper
References : Posted by Jon Watte

Notes :
A favourite of mine is using a sin() function instead.
This will have the "unfortunate" side effect of removing
odd harmonics if you take it to the extreme: a triangle
wave gets mapped to a pure sine wave.
This will work with a going from .1 or so to a= 5 and bigger!
The mathematical limits for a = 0 actually turns it into a linear
function at that point, but unfortunately FPUs aren't that good
with calculus :-) Once a goes above 1, you start getting clipping
in addition to the "soft" wave shaping. It starts getting into
more of an effect and less of a mastering tool, though :-)

Seeing as this is just various forms of wave shaping, you
could do it all with a look-up table, too. In my version, that would
get rid of the somewhat-expensive sin() function.


Code :
(input: a == "overdrive amount")

z = M_PI * a;
s = 1/sin(z)
b = 1/a

if (x > b)
  f(x) = 1
else
  f(x) = sin(z*x)*s


1 comment(s) | add a comment | nofrills version


Waveshaper

References : Posted by Partice Tarrabia and Bram de Jong

Notes :
amount should be in [-1..1[ Plot it and stand back in astonishment! ;)

Code :
x = input in [-1..1]
y = output
k = 2*amount/(1-amount);

f(x) = (1+k)*x/(1+k*abs(x))


1 comment(s) | add a comment | nofrills version


Waveshaper (simple description)

Type : Polynomial; Distortion
References : Posted by Jon Watte

Notes :
> The other question; what's a 'waveshaper' algorithm. Is it simply another
> word for distortion?

A typical "waveshaper" is some function which takes an input sample value
X and transforms it to an output sample X'. A typical implementation would
be a look-up table of some number of points, and some level of interpolation
between those points (say, cubic). When people talk about a wave shaper,
this is most often what they mean. Note that a wave shaper, as opposed to a
filter, does not have any state. The mapping from X -> X' is stateless.

Some wave shapers are implemented as polynomials, or using other math
functions. Hard clipping is a wave shaper implemented using the min() and
max() functions (or the three-argument clamp() function, which is the same
thing). A very mellow and musical-sounding distortion is implemented using
a third-degree polynomial; something like X' = (3/2)X - (1/2)X^3. The nice
thing with polynomial wave shapers is that you know that the maximum they
will expand bandwidth is their order. Thus, you need to oversample 3x to
make sure that a third-degree polynomial is aliasing free. With a lookup
table based wave shaper, you don't know this (unless you treat an N-point
table as an N-point polynomial :-)


Code :
float waveshape_distort( float in ) {
  return 1.5f * in - 0.5f * in *in * in;
}


no comments on this item | add a comment | nofrills version


Waveshaper :: Gloubi-boulga

References : Laurent de Soras on IRC

Notes :
Multiply input by gain before processing

Code :
const double x = input * 0.686306;
const double a = 1 + exp (sqrt (fabs (x)) * -0.75);
output = (exp (x) - exp (-x * a)) / (exp (x) + exp (-x));


2 comment(s) | add a comment | nofrills version