|
|
|
|
 |
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 |
|
 |
|
|
|
|
|
 |
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 |
|
 |
|
|
|
|
|
 |
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 |
|
 |
|
|
|
|
|
 |
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 |
|
 |
|
|
|
|
|
 |
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 |
|
 |
|
|
|
|
|
 |
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 |
|
 |
|
|
|
|