|
|
 |
(Allmost) Ready-to-use oscillators
Type : waveform generation References : Ross Bencina, Olli Niemitalo, ...
Notes : Ross Bencina: original source code poster
Olli Niemitalo: UpdateWithCubicInterpolation
Code : //this code is meant as an EXAMPLE
//uncomment if you need an FM oscillator
//define FM_OSCILLATOR
/*
members are:
float phase;
int TableSize;
float sampleRate;
float *table, dtable0, dtable1, dtable2, dtable3;
->these should be filled as folows... (remember to wrap around!!!)
table[i] = the wave-shape
dtable0[i] = table[i+1] - table[i];
dtable1[i] = (3.f*(table[i]-table[i+1])-table[i-1]+table[i+2])/2.f
dtable2[i] = 2.f*table[i+1]+table[i-1]-(5.f*table[i]+table[i+2])/2.f
dtable3[i] = (table[i+1]-table[i-1])/2.f
*/
float Oscillator::UpdateWithoutInterpolation(float frequency)
{
int i = (int) phase;
phase += (sampleRate/(float TableSize)/frequency;
if(phase >= (float)TableSize)
phase -= (float)TableSize;
#ifdef FM_OSCILLATOR
if(phase < 0.f)
phase += (float)TableSize;
#endif
return table[i] ;
}
float Oscillator::UpdateWithLinearInterpolation(float frequency)
{
int i = (int) phase;
float alpha = phase - (float) i;
phase += (sampleRate/(float)TableSize)/frequency;
if(phase >= (float)TableSize)
phase -= (float)TableSize;
#ifdef FM_OSCILLATOR
if(phase < 0.f)
phase += (float)TableSize;
#endif
/*
dtable0[i] = table[i+1] - table[i]; //remember to wrap around!!!
*/
return table[i] + dtable0[i]*alpha;
}
float Oscillator::UpdateWithCubicInterpolation( float frequency )
{
int i = (int) phase;
float alpha = phase - (float) i;
phase += (sampleRate/(float)TableSize)/frequency;
if(phase >= (float)TableSize)
phase -= (float)TableSize;
#ifdef FM_OSCILLATOR
if(phase < 0.f)
phase += (float)TableSize;
#endif
/* //remember to wrap around!!!
dtable1[i] = (3.f*(table[i]-table[i+1])-table[i-1]+table[i+2])/2.f
dtable2[i] = 2.f*table[i+1]+table[i-1]-(5.f*table[i]+table[i+2])/2.f
dtable3[i] = (table[i+1]-table[i-1])/2.f
*/
return ((dtable1[i]*alpha + dtable2[i])*alpha + dtable3[i])*alpha+table[i];
}
9 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
AM Formantic Synthesis
References : Posted by Paul Sernine
Notes : Here is another tutorial from Doc Rochebois.
It performs formantic synthesis without filters and without grains. Instead, it uses "double carrier amplitude modulation" to pitch shift formantic waveforms. Just beware the phase relationships to avoid interferences. Some patches of the DX7 used the same trick but phase interferences were a problem. Here, Thierry Rochebois avoids them by using cosine-phased waveforms.
Various formantic waveforms are precalculated and put in tables, they correspond to different formant widths.
The runtime uses many intances (here 4) of these and pitch shifts them with double carriers (to preserve the harmonicity of the signal).
This is a tutorial code, it can be optimized in many ways.
Have Fun
Paul
Code : // FormantsAM.cpp
// Thierry Rochebois' "Formantic Synthesis by Double Amplitude Modulation"
// Based on a tutorial by Thierry Rochebois.
// Comments by Paul Sernine.
// The spectral content of the signal is obtained by adding amplitude modulated formantic
// waveforms. The amplitude modulations spectraly shift the formantic waveforms.
// Continuous spectral shift, without losing the harmonic structure, is obtained
// by using crossfaded double carriers (multiple of the base frequency).
// To avoid unwanted interference artifacts, phase relationships must be of the
// "cosine type".
// The output is a 44100Hz 16bit stereo PCM file.
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
//Approximates cos(pi*x) for x in [-1,1].
inline float fast_cos(const float x)
{
float x2=x*x;
return 1+x2*(-4+2*x2);
}
//Length of the table
#define L_TABLE (256+1) //The last entry of the table equals the first (to avoid a modulo)
//Maximal formant width
#define I_MAX 64
//Table of formants
float TF[L_TABLE*I_MAX];
//Formantic function of width I (used to fill the table of formants)
float fonc_formant(float p,const float I)
{
float a=0.5f;
int hmax=int(10*I)>L_TABLE/2?L_TABLE/2:int(10*I);
float phi=0.0f;
for(int h=1;h<hmax;h++)
{
phi+=3.14159265359f*p;
float hann=0.5f+0.5f*fast_cos(h*(1.0f/hmax));
float gaussienne=0.85f*exp(-h*h/(I*I));
float jupe=0.15f;
float harmonique=cosf(phi);
a+=hann*(gaussienne+jupe)*harmonique;
}
return a;
}
//Initialisation of the table TF with the fonction fonc_formant.
void init_formant(void)
{ float coef=2.0f/(L_TABLE-1);
for(int I=0;I<I_MAX;I++)
for(int P=0;P<L_TABLE;P++)
TF[P+I*L_TABLE]=fonc_formant(-1+P*coef,float(I));
}
//This function emulates the function fonc_formant
// thanks to the table TF. A bilinear interpolation is
// performed
float formant(float p,float i)
{
i=i<0?0:i>I_MAX-2?I_MAX-2:i; // width limitation
float P=(L_TABLE-1)*(p+1)*0.5f; // phase normalisation
int P0=(int)P; float fP=P-P0; // Integer and fractional
int I0=(int)i; float fI=i-I0; // parts of the phase (p) and width (i).
int i00=P0+L_TABLE*I0; int i10=i00+L_TABLE;
//bilinear interpolation.
return (1-fI)*(TF[i00] + fP*(TF[i00+1]-TF[i00]))
+ fI*(TF[i10] + fP*(TF[i10+1]-TF[i10]));
}
// Double carrier.
// h : position (float harmonic number)
// p : phase
float porteuse(const float h,const float p)
{
float h0=floor(h); //integer and
float hf=h-h0; //decimal part of harmonic number.
// modulos pour ramener p*h0 et p*(h0+1) dans [-1,1]
float phi0=fmodf(p* h0 +1+1000,2.0f)-1.0f;
float phi1=fmodf(p*(h0+1)+1+1000,2.0f)-1.0f;
// two carriers.
float Porteuse0=fast_cos(phi0); float Porteuse1=fast_cos(phi1);
// crossfade between the two carriers.
return Porteuse0+hf*(Porteuse1-Porteuse0);
}
int main()
{
//Formant table for various french vowels (you can add your own)
float F1[]={ 730, 200, 400, 250, 190, 350, 550, 550, 450};
float A1[]={ 1.0f, 0.5f, 1.0f, 1.0f, 0.7f, 1.0f, 1.0f, 0.3f, 1.0f};
float F2[]={ 1090, 2100, 900, 1700, 800, 1900, 1600, 850, 1100};
float A2[]={ 2.0f, 0.5f, 0.7f, 0.7f,0.35f, 0.3f, 0.5f, 1.0f, 0.7f};
float F3[]={ 2440, 3100, 2300, 2100, 2000, 2500, 2250, 1900, 1500};
float A3[]={ 0.3f,0.15f, 0.2f, 0.4f, 0.1f, 0.3f, 0.7f, 0.2f, 0.2f};
float F4[]={ 3400, 4700, 3000, 3300, 3400, 3700, 3200, 3000, 3000};
float A4[]={ 0.2f, 0.1f, 0.2f, 0.3f, 0.1f, 0.1f, 0.3f, 0.2f, 0.3f};
float f0,dp0,p0=0.0f;
int F=7; //number of the current formant preset
float f1,f2,f3,f4,a1,a2,a3,a4;
f1=f2=f3=f4=100.0f;a1=a2=a3=a4=0.0f;
init_formant();
FILE *f=fopen("sortie.pcm","wb");
for(int ns=0;ns<10*44100;ns++)
{
if(0==(ns%11025)){F++;F%=8;} //formant change
f0=12*powf(2.0f,4-4*ns/(10*44100.0f)); //sweep
f0*=(1.0f+0.01f*sinf(ns*0.0015f)); //vibrato
dp0=f0*(1/22050.0f);
float un_f0=1.0f/f0;
p0+=dp0; //phase increment
p0-=2*(p0>1);
{ //smoothing of the commands.
float r=0.001f;
f1+=r*(F1[F]-f1);f2+=r*(F2[F]-f2);f3+=r*(F3[F]-f3);f4+=r*(F4[F]-f4);
a1+=r*(A1[F]-a1);a2+=r*(A2[F]-a2);a3+=r*(A3[F]-a3);a4+=r*(A4[F]-a4);
}
//The f0/fn coefficients stand for a -3dB/oct spectral enveloppe
float out=
a1*(f0/f1)*formant(p0,100*un_f0)*porteuse(f1*un_f0,p0)
+0.7f*a2*(f0/f2)*formant(p0,120*un_f0)*porteuse(f2*un_f0,p0)
+ a3*(f0/f3)*formant(p0,150*un_f0)*porteuse(f3*un_f0,p0)
+ a4*(f0/f4)*formant(p0,300*un_f0)*porteuse(f4*un_f0,p0);
short s=short(15000.0f*out);
fwrite(&s,2,1,f);fwrite(&s,2,1,f); //fichier raw pcm stereo
}
fclose(f);
return 0;
}
5 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Another cheap sinusoidal LFO
References : Posted by info[at]e-phonic[dot]com
Notes : Some pseudo code for a easy to calculate LFO.
You can even make a rough triangle wave out of this by substracting the output of 2 of these with different phases.
PJ
Code : r = the rate 0..1
--------------
p += r
if(p > 1) p -= 2;
out = p*(1-abs(p));
--------------
5 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
another LFO class
References : Posted by mdsp Linked file : LFO.zip
Notes : This LFO uses an unsigned 32-bit phase and increment whose 8 Most Significant Bits adress a Look-up table while the 24 Least Significant Bits are used as the fractionnal part.
Note: As the phase overflow automatically, the index is always in the range 0-255.
It performs linear interpolation, but it is easy to add other types of interpolation.
Don't know how good it could be as an oscillator, but I found it good enough for a LFO.
BTW there is also different kind of waveforms.
Modifications:
We could use phase on 64-bit or change the proportion of bits used by the index and the fractionnal part.
3 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
antialiased square generator
Type : 1st April edition References : Posted by Paul Sernine
Notes : It is based on a code by Thierry Rochebois, obfuscated by me.
It generates a 16bit MONO raw pcm file. Have Fun.
Code : //sqrfish.cpp
#include <math.h>
#include <stdio.h>
//obfuscation P.Sernine
int main() {float ccc,cccc=0,CC=0,cc=0,CCCC,
CCC,C,c; FILE *CCCCCCC=fopen("sqrfish.pcm",
"wb" ); int ccccc= 0; float CCCCC=6.89e-6f;
for(int CCCCCC=0;CCCCCC<1764000;CCCCCC++ ){
if(!(CCCCCC%7350)){if(++ccccc>=30){ ccccc =0;
CCCCC*=2;}CCC=1;}ccc=CCCCC*expf(0.057762265f*
"aiakahiafahadfaiakahiahafahadf"[ccccc]);CCCC
=0.75f-1.5f*ccc;cccc+=ccc;CCC*=0.9999f;cccc-=
2*(cccc>1);C=cccc+CCCC*CC; c=cccc+CCCC*cc; C
-=2*(C>1);c-=2*(c>1);C+=2*(C<-1); c+=1+2
*(c<-1);c-=2*(c>1);C=C*C*(2 *C*C-4);
c=c*c*(2*c*c-4); short cccccc=short(15000.0f*
CCC*(C-c )*CCC);CC=0.5f*(1+C+CC);cc=0.5f*(1+
c+cc); fwrite(&cccccc,2,1,CCCCCCC);}
//algo by Thierry Rochebois
fclose(CCCCCCC);
return 0000000;}
8 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Arbitary shaped band-limited waveform generation (using oversampling and low-pass filtering)
References : Posted by remage[AT]kac[DOT]poliod[DOT]hu Code : Arbitary shaped band-limited waveform generation
(using oversampling and low-pass filtering)
There are many articles about band-limited waveform synthesis techniques, that provide correct and fast methods for generating classic analogue waveforms, such as saw, pulse, and triangle wave. However, generating arbitary shaped band-limited waveforms, such as the "sawsin" shape (found in this source-code archive), seems to be quite hard using these techniques.
My analogue waveforms are generated in a _very_ high sampling rate (actually it's 1.4112 GHz for 44.1 kHz waveforms, using 32x oversampling). Using this sample-rate, the amplitude of the aliasing harmonics are negligible (the base analogue waveforms has exponentially decreasing harmonics amplitudes).
Using a 511-tap windowed sync FIR filter (with Blackman-Harris window, and 12 kHz cutoff frequency) the harmonics above 20 kHz are killed, the higher harmonics (that cause the sharp overshoot at step response) are dampened.
The filtered signal downsampled to 44.1 kHz contains the audible (non-aliased) harmonics only.
This waveform synthesis is performed for wavetables of 4096, 2048, 1024, ... 8, 4, 2 samples. The real-time signal is interpolated from these waveform-tables, using Hermite-(cubic-)interpolation for the waveforms, and linear interpolation between the two wavetables near the required note.
This procedure is quite time-consuming, but the whole waveform (or, in my implementation, the whole waveform-set) can be precalculated (or saved at first launch of the synth) and reloaded at synth initialization.
I don't know if this is a theoretically correct solution, but the waveforms sound good (no audible aliasing). Please let me know if I'm wrong...
5 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Audiable alias free waveform gen using width sine
Type : Very simple References : Posted by joakim[DOT]dahlstrom[AT]ongame[DOT]com
Notes : Warning, my english abilities is terribly limited.
How ever, the other day when finally understanding what bandlimited wave creation is (i am a noobie, been doing DSP stuf on and off for a half/year) it hit me i can implement one little part in my synths. It's all about the freq (that i knew), very simple you can reduce alias (the alias that you can hear that is) extremely by keeping track of your frequence, the way i solved it is using a factor, afact = 1 - sin(f*2PI). This means you can do audiable alias free synthesis without very complex algorithms or very huge tables, even though the sound becomes kind of low-filtered.
Propably something like this is mentioned b4, but incase it hasn't this is worth looking up
The psuedo code describes it more.
// Druttis
Code : f := freq factor, 0 - 0.5 (0 to half samplingrate)
afact(f) = 1 - sin(f*2PI)
t := time (0 to ...)
ph := phase shift (0 to 1)
fm := freq mod (0 to 1)
sine(t,f,ph,fm) = sin((t*f+ph)*2PI + 0.5PI*fm*afact(f))
fb := feedback (0 to 1) (1 max saw)
saw(t,f,ph,fm,fb) = sine(t,f,ph,fb*sine(t-1,f,ph,fm))
pm := pulse mod (0 to 1) (1 max pulse)
pw := pulse width (0 to 1) (1 square)
pulse(t,f,ph,fm,fb,pm,pw) = saw(t,f,ph,fm,fb) - (t,f,ph+0.5*pw,fm,fb) * pm
I am not completely sure about fm for saw & pulse since i cant test that atm. but it should work :) otherwise just make sure fm are 0 for saw & pulse.
As you can see the saw & pulse wave are very variable.
// Druttis
5 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Band Limited waveforms my way
Type : classic Sawtooth example References : Posted by Anton Savov (antto mail bg)
Notes : This is my <ugly> C++ code for generating a single cycle of a Sawtooth in a table
normaly i create my "fundamental" table big enough to hold on around 20-40Hz in the current Sampling rate
also, i create the table twice as big, i do "mip-maps" then
so the size should be a power of two, say 1024 for 44100Hz = 44100/1024 = ~43.066Hz
then the mip-maps are with decreasing sizes (twice) 512, 256, 128, 64, 32, 16, 8, 4, and 2
if the "gibbs" effect is what i think it is - then i have a simple solution
here is my crappy code:
Code : int sz = 1024; // the size of the table
int i = 0;
float *table; // pointer to the table
double scale = 1.0;
double pd; // phase
double omega = 1.0 / (double)(sz);
while (i < sz)
{
double amp = scale;
double x = 0.0; // the sample
double h = 1; // harmonic number (starts from 1)
double dd; // fix high frequency "ring"
pd = (double)(i) / (double)(sz); // calc phase
double hpd = pd; // phase of the harmonic
while (true) // start looping for this sample
{
if ((omega * h) < 0.5) // harmonic frequency is in range?
{
dd = cos(omega * h * 2 * pi);
x = x + (amp * dd * sin(hpd * 2 * pi));
h = h + 1;
hpd = pd * h;
amp = 1.0 / h;
}
else { break; }
}
table[i] = x;
++i;
}
the peaks are around +/- 0.8
a square can be generated by just changing h = h+2; the peaks would be +/- 0.4
any bugs/improvements?
3 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Bandlimited sawtooth synthesis
Type : DSF BLIT References : Posted by emanuel.landeholm [AT] telia.com Linked file : synthesis002.txt
Notes : This is working code for synthesizing a bandlimited sawtooth waveform. The algorithm is DSF BLIT + leaky integrator. Includes driver code.
There are two parameters you may tweak:
1) Desired attenuation at nyquist. A low value yields a duller sawtooth but gets rid of those annoying CLICKS when sweeping the frequency up real high. Must be strictly less than 1.0!
2) Integrator leakiness/cut off. Affects the shape of the waveform to some extent, esp. at the low end. Ideally you would want to set this low, but too low a setting will give you problems with DC.
Have fun!
/Emanuel Landeholm
(see linked file)
2 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Bandlimited waveforms...
References : Posted by Paul Kellet
Notes : (Quoted from Paul's mail)
Below is another waveform generation method based on a train of sinc functions (actually an alternating loop along a sinc between t=0 and t=period/2).
The code integrates the pulse train with a dc offset to get a sawtooth, but other shapes can be made in the usual ways... Note that 'dc' and 'leak' may need to be adjusted for very high or low frequencies.
I don't know how original it is (I ought to read more) but it is of usable quality, particularly at low frequencies. There's some scope for optimisation by using a table for sinc, or maybe a a truncated/windowed sinc?
I think it should be possible to minimise the aliasing by fine tuning 'dp' to slightly less than 1 so the sincs join together neatly, but I haven't found the best way to do it. Any comments gratefully received.
Code : float p=0.0f; //current position
float dp=1.0f; //change in postion per sample
float pmax; //maximum position
float x; //position in sinc function
float leak=0.995f; //leaky integrator
float dc; //dc offset
float saw; //output
//set frequency...
pmax = 0.5f * getSampleRate() / freqHz;
dc = -0.498f/pmax;
//for each sample...
p += dp;
if(p < 0.0f)
{
p = -p;
dp = -dp;
}
else if(p > pmax)
{
p = pmax + pmax - p;
dp = -dp;
}
x= pi * p;
if(x < 0.00001f)
x=0.00001f; //don't divide by 0
saw = leak*saw + dc + (float)sin(x)/(x);
3 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Butterworth
Type : LPF 24dB/Oct References : Posted by Christian[at]savioursofsoul[dot]de Code : First calculate the prewarped digital frequency:
K = tan(Pi * Frequency / Samplerate);
Now calc some intermediate variables: (see 'Factors of Polynoms' at http://en.wikipedia.org/wiki/Butterworth_filter, especially if you want a higher order like 48dB/Oct)
a = 0.76536686473 * Q * K;
b = 1.84775906502 * Q * K;
K = K*K; (to optimize it a little bit)
Calculate the first biquad:
A0 = (K+a+1);
A1 = 2*(1-K);
A2 =(a-K-1);
B0 = K;
B1 = 2*B0;
B2 = B0;
Calculate the second biquad:
A3 = (K+b+1);
A4 = 2*(1-K);
A5 = (b-K-1);
B3 = K;
B4 = 2*B3;
B5 = B3;
Then calculate the output as follows:
Stage1 = B0*Input + State0;
State0 = B1*Input + A1/A0*Stage1 + State1;
State1 = B2*Input + A2/A0*Stage1;
Output = B3*Stage1 + State2;
State2 = B4*Stage1 + A4/A3*Output + State2;
State3 = B5*Stage1 + A5/A3*Output;
9 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
C# Oscilator class
Type : Sine, Saw, Variable Pulse, Triangle, C64 Noise References : Posted by neotec
Notes : Parameters:
Pitch: The Osc's pitch in Cents [0 - 14399] startig at A -> 6.875Hz
Pulsewidth: [0 - 65535] -> 0% to 99.99%
Value: The last Output value, a set to this property 'syncs' the Oscilator
Code : public class SynthOscilator
{
public enum OscWaveformType
{
SAW, PULSE, TRI, NOISE, SINE
}
public int Pitch
{
get
{
return this._Pitch;
}
set
{
this._Pitch = this.MinMax(0, value, 14399);
this.OscStep = WaveSteps[this._Pitch];
}
}
public int PulseWidth
{
get
{
return this._PulseWidth;
}
set
{
this._PulseWidth = this.MinMax(0, value, 65535);
}
}
public OscWaveformType Waveform
{
get
{
return this._WaveForm;
}
set
{
this._WaveForm = value;
}
}
public int Value
{
get
{
return this._Value;
}
set
{
this._Value = 0;
this.OscNow = 0;
}
}
private int _Pitch;
private int _PulseWidth;
private int _Value;
private OscWaveformType _WaveForm;
private int OscNow;
private int OscStep;
private int ShiftRegister;
public const double BaseFrequence = 6.875;
public const int SampleRate = 44100;
public static int[] WaveSteps = new int[0];
public static int[] SineTable = new int[0];
public SynthOscilator()
{
if (WaveSteps.Length == 0)
this.CalcSteps();
if (SineTable.Length == 0)
this.CalcSine();
this._Pitch = 7200;
this._PulseWidth = 32768;
this._WaveForm = OscWaveformType.SAW;
this.ShiftRegister = 0x7ffff8;
this.OscNow = 0;
this.OscStep = WaveSteps[this._Pitch];
this._Value = 0;
}
private void CalcSteps()
{
WaveSteps = new int[14400];
for (int i = 0; i < 14400; i++)
{
double t0, t1, t2;
t0 = Math.Pow(2.0, (double)i / 1200.0);
t1 = BaseFrequence * t0;
t2 = (t1 * 65536.0) / (double)this.SampleRate;
WaveSteps[i] = (int)Math.Round(t2 * 4096.0);
}
}
private void CalcSine()
{
SineTable = new int[65536];
double s = Math.PI / 32768.0;
for (int i = 0; i < 65536; i++)
{
double v = Math.Sin((double)i * s) * 32768.0;
int t = (int)Math.Round(v) + 32768;
if (t < 0)
t = 0;
else if (t > 65535)
t = 65535;
SineTable[i] = t;
}
}
public override int Run()
{
int ret = 32768;
int osc = this.OscNow >> 12;
switch (this._WaveForm)
{
case OscWaveformType.SAW:
ret = osc;
break;
case OscWaveformType.PULSE:
if (osc < this.PulseWidth)
ret = 65535;
else
ret = 0;
break;
case OscWaveformType.TRI:
if (osc < 32768)
ret = osc << 1;
else
ret = 131071 - (osc << 1);
break;
case OscWaveformType.NOISE:
ret = ((this.ShiftRegister & 0x400000) >> 11) |
((this.ShiftRegister & 0x100000) >> 10) |
((this.ShiftRegister & 0x010000) >> 7) |
((this.ShiftRegister & 0x002000) >> 5) |
((this.ShiftRegister & 0x000800) >> 4) |
((this.ShiftRegister & 0x000080) >> 1) |
((this.ShiftRegister & 0x000010) << 1) |
((this.ShiftRegister & 0x000004) << 2);
ret <<= 4;
break;
case OscWaveformType.SINE:
ret = SynthTools.SineTable[osc];
break;
default:
break;
}
this.OscNow += this.OscStep;
if (this.OscNow > 0xfffffff)
{
int bit0 = ((this.ShiftRegister >> 22) ^ (this.ShiftRegister >> 17)) & 0x1;
this.ShiftRegister <<= 1;
this.ShiftRegister &= 0x7fffff;
this.ShiftRegister |= bit0;
}
this.OscNow &= 0xfffffff;
this._Value = ret - 32768;
return this._Value;
}
public int MinMax(int a, int b, int c)
{
if (b < a)
return a;
else if (b > c)
return c;
else
return b;
}
}
no comments on this item | add a comment | nofrills version |
|
 |
|
|
|
 |
C++ gaussian noise generation
Type : gaussian noise generation References : Posted by paul[at]expdigital[dot]co[dot]uk
Notes : References :
Tobybears delphi noise generator was the basis. Simply converted it to C++.
Link for original is:
http://www.musicdsp.org/archive.php?classid=0#129
The output is in noise.
Code : /* Include requisits */
#include <cstdlib>
#include <ctime>
/* Generate a new random seed from system time - do this once in your constructor */
srand(time(0));
/* Setup constants */
const static int q = 15;
const static float c1 = (1 << q) - 1;
const static float c2 = ((int)(c1 / 3)) + 1;
const static float c3 = 1.f / c1;
/* random number in range 0 - 1 not including 1 */
float random = 0.f;
/* the white noise */
float noise = 0.f;
for (int i = 0; i < numSamples; i++)
{
random = ((float)rand() / (float)(RAND_MAX + 1));
noise = (2.f * ((random * c2) + (random * c2) + (random * c2)) - 3.f * (c2 - 1.f)) * c3;
}
3 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
chebyshev waveshaper (using their recursive definition)
Type : chebyshev References : Posted by mdsp
Notes : someone asked for it on kvr-audio.
I use it in an unreleased additive synth.
There's no oversampling needed in my case since I feed it with a pure sinusoid and I control the order to not have frequencies above Fs/2. Otherwise you should oversample by the order you'll use in the function or bandlimit the signal before the waveshaper. unless you really want that aliasing effect... :)
I hope the code is self-explaining, otherwise there's plenty of sites explaining chebyshev polynoms and their applications.
Code : float chebyshev(float x, float A[], int order)
{
// To = 1
// T1 = x
// Tn = 2.x.Tn-1 - Tn-2
// out = sum(Ai*Ti(x)) , i C {1,..,order}
float Tn_2 = 1.0f;
float Tn_1 = x;
float Tn;
float out = A[0]*Tn_1;
for(int n=2;n<=order;n++)
{
Tn = 2.0f*x*Tn_1 - Tn_2;
out += A[n-1]*Tn;
Tn_2 = Tn_1;
Tn_1 = Tn;
}
return out;
}
4 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Cubic polynomial envelopes
Type : envellope generation References : Posted by Andy Mucho
Notes : This function runs from:
startlevel at Time=0
midlevel at Time/2
endlevel at Time
At moments of extreme change over small time, the function can generate out
of range (of the 3 input level) numbers, but isn't really a problem in
actual use with real numbers, and sensible/real times..
Code : time = 32
startlevel = 0
midlevel = 100
endlevel = 120
k = startlevel + endlevel - (midlevel * 2)
r = startlevel
s = (endlevel - startlevel - (2 * k)) / time
t = (2 * k) / (time * time)
bigr = r
bigs = s + t
bigt = 2 * t
for(int i=0;i<time;i++)
{
bigr = bigr + bigs
bigs = bigs + bigt
}
2 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Direct pink noise synthesis with auto-correlated generator
Type : 16-bit fixed-point References : Posted by RidgeRat
Notes : Canonical C++ class with minimum system dependencies, BUT you must provide your own uniform random number generator. Accurate range is a little over 9 octaves, degrading gracefully beyond this. Estimated deviations +-0.25 dB from ideal 1/f curve in range. Scaled to fit signed 16-bit range.
Code : // Pink noise class using the autocorrelated generator method.
// Method proposed and described by Larry Trammell "the RidgeRat" --
// see http://home.earthlink.net/~ltrammell/tech/newpink.htm
// There are no restrictions.
//
// ------------------------------------------------------------------
//
// This is a canonical, 16-bit fixed-point implementation of the
// generator in 32-bit arithmetic. There are only a few system
// dependencies.
//
// -- access to an allocator 'malloc' for operator new
// -- access to definition of 'size_t'
// -- assumes 32-bit two's complement arithmetic
// -- assumes long int is 32 bits, short int is 16 bits
// -- assumes that signed right shift propagates the sign bit
//
// It needs a separate URand class to provide uniform 16-bit random
// numbers on interval [1,65535]. The assumed class must provide
// methods to query and set the current seed value, establish a
// scrambled initial seed value, and evaluate uniform random values.
//
//
// ----------- header -----------------------------------------------
// pinkgen.h
#ifndef _pinkgen_h_
#define _pinkgen_h_ 1
#include <stddef.h>
#include <alloc.h>
// You must provide the uniform random generator class.
#ifndef _URand_h_
#include "URand.h"
#endif
class PinkNoise {
private:
// Coefficients (fixed)
static long int const pA[5];
static short int const pPSUM[5];
// Internal pink generator state
long int contrib[5]; // stage contributions
long int accum; // combined generators
void internal_clear( );
// Include a UNoise component
URand ugen;
public:
PinkNoise( );
PinkNoise( PinkNoise & );
~PinkNoise( );
void * operator new( size_t );
void pinkclear( );
short int pinkrand( );
} ;
#endif
// ----------- implementation ---------------------------------------
// pinkgen.cpp
#include "pinkgen.h"
// Static class data
long int const PinkNoise::pA[5] =
{ 14055, 12759, 10733, 12273, 15716 };
short int const PinkNoise::pPSUM[5] =
{ 22347, 27917, 29523, 29942, 30007 };
// Clear generator to a zero state.
void PinkNoise::pinkclear( )
{
int i;
for (i=0; i<5; ++i) { contrib[i]=0L; }
accum = 0L;
}
// PRIVATE, clear generator and also scramble the internal
// uniform generator seed.
void PinkNoise::internal_clear( )
{
pinkclear();
ugen.seed(0); // Randomizes the seed!
}
// Constructor. Guarantee that initial state is cleared
// and uniform generator scrambled.
PinkNoise::PinkNoise( )
{
internal_clear();
}
// Copy constructor. Preserve generator state from the source
// object, including the uniform generator seed.
PinkNoise::PinkNoise( PinkNoise & Source )
{
int i;
for (i=0; i<5; ++i) contrib[i]=Source.contrib[i];
accum = Source.accum;
ugen.seed( Source.ugen.seed( ) );
}
// Operator new. Just fetch required object storage.
void * PinkNoise::operator new( size_t size )
{
return malloc(size);
}
// Destructor. No special action required.
PinkNoise::~PinkNoise( ) { /* NIL */ }
// Coding artifact for convenience
#define UPDATE_CONTRIB(n) \
{ \
accum -= contrib[n]; \
contrib[n] = (long)randv * pA[n]; \
accum += contrib[n]; \
break; \
}
// Evaluate next randomized 'pink' number with uniform CPU loading.
short int PinkNoise::pinkrand( )
{
short int randu = ugen.urand() & 0x7fff; // U[0,32767]
short int randv = (short int) ugen.urand(); // U[-32768,32767]
// Structured block, at most one update is performed
while (1)
{
if (randu < pPSUM[0]) UPDATE_CONTRIB(0);
if (randu < pPSUM[1]) UPDATE_CONTRIB(1);
if (randu < pPSUM[2]) UPDATE_CONTRIB(2);
if (randu < pPSUM[3]) UPDATE_CONTRIB(3);
if (randu < pPSUM[4]) UPDATE_CONTRIB(4);
break;
}
return (short int) (accum >> 16);
}
// ----------- application -------------------------------
short int pink_signal[1024];
void example(void)
{
PinkNoise pinkgen;
int i;
for (i=0; i<1024; ++i) pink_signal[i] = pinkgen.pinkrand();
}
no comments on this item | add a comment | nofrills version |
|
 |
|
|
|
 |
Discrete Summation Formula (DSF)
References : Stylson, Smith and others... (posted by Alexander Kritov)
Notes : Buzz uses this type of synth.
For cool sounds try to use variable,
for example a=exp(-x/12000)*0.8 // x- num.samples
Code : double DSF (double x, // input
double a, // a<1.0
double N, // N<SmplFQ/2,
double fi) // phase
{
double s1 = pow(a,N-1.0)*sin((N-1.0)*x+fi);
double s2 = pow(a,N)*sin(N*x+fi);
double s3 = a*sin(x+fi);
double s4 =1.0 - (2*a*cos(x)) +(a*a);
if (s4==0)
return 0;
else
return (sin(fi) - s3 - s2 +s1)/s4;
}
6 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Drift generator
Type : Random References : Posted by quintosardo[AT]yahoo[DOT]it
Notes : I use this drift to modulate any sound parameter of my synth.
It is very effective if it slightly modulates amplitude or frequency of an FM modulator.
It is based on an incremental random variable, sine-warped.
I like it because it is "continuous" (as opposite to "sample and hold"), and I can set variation rate and max variation.
It can go to upper or lower constraint (+/- max drift) but it gradually decreases rate of variation when approaching to the limit.
I use it exactly as an LFO (-1.f .. +1.f)
I use a table for sin instead of sin() function because this way I can change random distribution, by selecting a different curve (different table) from sine...
I hope that it is clear ... (sigh... :-)
Bye!!!
P.S. Thank you for help in previous submission ;-)
Code : const int kSamples //Number of samples in fSinTable below
float fSinTable[kSamples] // Tabulated sin() [0 - 2pi[ amplitude [-1.f .. 1.f]
float fWhere// Index
float fRate // Max rate of variation
float fLimit //max or min value
float fDrift // Output
//I assume that random() is a number from 0.f to 1.f, otherwise scale it
fWhere += fRate * random()
//I update this drift in a long-term cycle, so I don't care of branches
if (fWhere >= 1.f) fWhere -= 1.f
else if (fWhere < 0.f) sWhere += 1.f
fDrift = fLimit * fSinTable[(long) (fWhere * kSamples)]
1 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
DSF (super-set of BLIT)
Type : matlab code References : Posted by David Lowenfels
Notes : Discrete Summation Formula ala Moorer
computes equivalent to sum{k=0:N-1}(a^k * sin(beta + k*theta))
modified from Emanuel Landeholm's C code
output should never clip past [-1,1]
If using for BLIT synthesis for virtual analog:
N = maxN;
a = attn_at_Nyquist ^ (1/maxN); %hide top harmonic popping in and out when sweeping frequency
beta = pi/2;
num = 1 - a^N * cos(N*theta) - a*( cos(theta) - a^N * cos(N*theta - theta) ); %don't waste time on beta
You can also get growing harmonics if a > 1, but the min statement in the code must be removed, and the scaling will be weird.
Code : function output = dsf( freq, a, H, samples, beta)
%a = rolloff coeffecient
%H = number of harmonic overtones (fundamental not included)
%beta = harmonic phase shift
samplerate = 44.1e3;
freq = freq/samplerate; %normalize frequency
bandlimit = samplerate / 2; %Nyquist
maxN = 1 + floor( bandlimit / freq ); %prevent aliasing
N = min(H+2,maxN);
theta = 2*pi * phasor(freq, samples);
epsilon = 1e-6;
a = min(a, 1-epsilon); %prevent divide by zero
num = sin(beta) - a*sin(beta-theta) - a^N*sin(beta + N*theta) + a^(N+1)*sin(beta+(N-1)*theta);
den = (1 + a * ( a - 2*cos(theta) ));
output = 2*(num ./ den - 1) * freq; %subtract by one to remove DC, scale by freq to normalize
output = output * maxN/N; %OPTIONAL: rescale to give louder output as rolloff increases
function out = phasor(normfreq, samples);
out = mod( (0:samples-1)*normfreq , 1);
out = out * 2 - 1; %make bipolar
1 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Easy noise generation
Type : White Noise References : Posted by mail[AT]ihsan-dsp[DOT]com
Notes : Easy noise generation,
in .hpp,
b_noise = 19.1919191919191919191919191919191919191919;
alternatively, the number 19 below can be replaced with a number of your choice, to get that particular flavour of noise.
Regards,
Ove Karlsen.
Code : b_noise = b_noise * b_noise;
int i_noise = b_noise;
b_noise = b_noise - i_noise;
double b_noiseout;
b_noiseout = b_noise - 0.5;
b_noise = b_noise + 19;
7 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Fast Exponential Envelope Generator
References : Posted by Christian Schoenebeck
Notes : The naive way to implement this would be to use a exp() call for each point
of the envelope. Unfortunately exp() is quite a heavy function for most
CPUs, so here is a numerical, much faster way to compute an exponential
envelope (performance gain measured in benchmark: about factor 100 with a
Intel P4, gcc -O3 --fast-math -march=i686 -mcpu=i686).
Note: you can't use a value of 0.0 for levelEnd. Instead you have to use an
appropriate, very small value (e.g. 0.001 should be sufficiently small
enough).
Code : const float sampleRate = 44100;
float coeff;
float currentLevel;
void init(float levelBegin, float levelEnd, float releaseTime) {
currentLevel = levelBegin;
coeff = (log(levelEnd) - log(levelBegin)) /
(releaseTime * sampleRate);
}
inline void calculateEnvelope(int samplePoints) {
for (int i = 0; i < samplePoints; i++) {
currentLevel += coeff * currentLevel;
// do something with 'currentLevel' here
...
}
}
14 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Fast LFO in Delphi...
References : Posted by Dambrin Didier ( gol [AT] e-officedirect [DOT] com ) Linked file : LFOGenerator.zip
Notes : [from Didier's mail...]
[see attached zip file too!]
I was working on a flanger, & needed an LFO for it. I first used a Sin(), but it was too slow, then tried a big wavetable, but it wasn't accurate enough.
I then checked the alternate sine generators from your web site, & while they're good, they all can drift, so you're also wasting too much CPU in branching for the drift checks.
So I made a quick & easy linear LFO, then a sine-like version of it. Can be useful for LFO's, not to output as sound.
If has no branching & is rather simple. 2 Abs() but apparently they're fast. In all cases faster than a Sin()
It's in delphi, but if you understand it you can translate it if you want.
It uses a 32bit integer counter that overflows, & a power for the sine output.
If you don't know delphi, $ is for hex (h at the end in c++?), Single is 32bit float, integer is 32bit integer (signed, normally).
Code : unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls, ComCtrls;
type
TForm1 = class(TForm)
PaintBox1: TPaintBox;
Bevel1: TBevel;
procedure PaintBox1Paint(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.PaintBox1Paint(Sender: TObject);
var n,Pos,Speed:Integer;
Output,Scale,HalfScale,PosMul:Single;
OurSpeed,OurScale:Single;
begin
OurSpeed:=100; // 100 samples per cycle
OurScale:=100; // output in -100..100
Pos:=0; // position in our linear LFO
Speed:=Round($100000000/OurSpeed);
// --- triangle LFO ---
Scale:=OurScale*2;
PosMul:=Scale/$80000000;
// loop
for n:=0 to 299 do
Begin
// inc our 32bit integer LFO pos & let it overflow. It will be seen as signed when read by the math unit
Pos:=Pos+Speed;
Output:=Abs(Pos*PosMul)-OurScale;
// visual
Paintbox1.Canvas.Pixels[n,Round(100+Output)]:=clRed;
End;
// --- sine-like LFO ---
Scale:=Sqrt(OurScale*4);
PosMul:=Scale/$80000000;
HalfScale:=Scale/2;
// loop
for n:=0 to 299 do
Begin
// inc our 32bit integer LFO pos & let it overflow. It will be seen as signed when read by the math unit
Pos:=Pos+Speed;
Output:=Abs(Pos*PosMul)-HalfScale;
Output:=Output*(Scale-Abs(Output));
// visual
Paintbox1.Canvas.Pixels[n,Round(100+Output)]:=clBlue;
End;
end;
end.
2 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Fast SIN approximation for usage in e.g. additive synthesizers
References : Posted by neotec
Notes : This code presents 2 'fastsin' functions. fastsin2 is less accurate than fastsin. In fact it's a simple taylor series, but optimized for integer phase.
phase is in 0 -> (2^32)-1 range and maps to 0 -> ~2PI
I get about 55000000 fastsin's per second on my P4,3.2GHz which would give a nice Kawai K5 emulation using 64 harmonics and 8->16 voices.
Code : float fastsin(UINT32 phase)
{
const float frf3 = -1.0f / 6.0f;
const float frf5 = 1.0f / 120.0f;
const float frf7 = -1.0f / 5040.0f;
const float frf9 = 1.0f / 362880.0f;
const float f0pi5 = 1.570796327f;
float x, x2, asin;
UINT32 tmp = 0x3f800000 | (phase >> 7);
if (phase & 0x40000000)
tmp ^= 0x007fffff;
x = (*((float*)&tmp) - 1.0f) * f0pi5;
x2 = x * x;
asin = ((((frf9 * x2 + frf7) * x2 + frf5) * x2 + frf3) * x2 + 1.0f) * x;
return (phase & 0x80000000) ? -asin : asin;
}
float fastsin2(UINT32 phase)
{
const float frf3 = -1.0f / 6.0f;
const float frf5 = 1.0f / 120.0f;
const float frf7 = -1.0f / 5040.0f;
const float f0pi5 = 1.570796327f;
float x, x2, asin;
UINT32 tmp = 0x3f800000 | (phase >> 7);
if (phase & 0x40000000)
tmp ^= 0x007fffff;
x = (*((float*)&tmp) - 1.0f) * f0pi5;
x2 = x * x;
asin = (((frf7 * x2 + frf5) * x2 + frf3) * x2 + 1.0f) * x;
return (phase & 0x80000000) ? -asin : asin;
}
2 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Fast sine wave calculation
Type : waveform generation References : James McCartney in Computer Music Journal, also the Julius O. Smith paper
Notes : (posted by Niels Gorisse)
If you change the frequency, the amplitude rises (pitch lower) or lowers (pitch rise) a LOT I fixed the first problem by thinking about what actually goes wrong. The answer was to recalculate the phase for that frequency and the last value, and then continue normally.
Code : Variables:
ip = phase of the first output sample in radians
w = freq*pi / samplerate
b1 = 2.0 * cos(w)
Init:
y1=sin(ip-w)
y2=sin(ip-2*w)
Loop:
y0 = b1*y1 - y2
y2 = y1
y1 = y0
output is in y0 (y0 = sin(ip + n*freq*pi / samplerate), n= 0, 1, 2, ... I *think*)
Later note by James McCartney:
if you unroll such a loop by 3 you can even eliminate the assigns!!
y0 = b1*y1 - y2
y2 = b1*y0 - y1
y1 = b1*y2 - y0
498 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Fast square wave generator
Type : NON-bandlimited osc... References : Posted by Wolfgang (wschneider[AT]nexoft.de)
Notes : Produces a square wave -1.0f .. +1.0f.
The resulting waveform is NOT band-limited, so it's propably of not much use for syntheis. It's rather useful for LFOs and the like, though.
Code : Idea: use integer overflow to avoid conditional jumps.
// init:
typedef unsigned long ui32;
float sampleRate = 44100.0f; // whatever
float freq = 440.0f; // 440 Hz
float one = 1.0f;
ui32 intOver = 0L;
ui32 intIncr = (ui32)(4294967296.0 / hostSampleRate / freq));
// loop:
(*((ui32 *)&one)) &= 0x7FFFFFFF; // mask out sign bit
(*((ui32 *)&one)) |= (intOver & 0x80000000);
intOver += intIncr;
2 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Fast Whitenoise Generator
Type : Whitenoise References : Posted by gerd[DOT]feldkirch[AT]web[DOT]de
Notes : This is Whitenoise... :o)
Code : float g_fScale = 2.0f / 0xffffffff;
int g_x1 = 0x67452301;
int g_x2 = 0xefcdab89;
void whitenoise(
float* _fpDstBuffer, // Pointer to buffer
unsigned int _uiBufferSize, // Size of buffer
float _fLevel ) // Noiselevel (0.0 ... 1.0)
{
_fLevel *= g_fScale;
while( _uiBufferSize-- )
{
g_x1 ^= g_x2;
*_fpDstBuffer++ = g_x2 * _fLevel;
g_x2 += g_x1;
}
}
9 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Gaussian White noise
References : Posted by Alexey Menshikov
Notes : Code I use sometimes, but don't remember where I ripped it from.
- Alexey Menshikov
Code : #define ranf() ((float) rand() / (float) RAND_MAX)
float ranfGauss (int m, float s)
{
static int pass = 0;
static float y2;
float x1, x2, w, y1;
if (pass)
{
y1 = y2;
} else {
do {
x1 = 2.0f * ranf () - 1.0f;
x2 = 2.0f * ranf () - 1.0f;
w = x1 * x1 + x2 * x2;
} while (w >= 1.0f);
w = (float)sqrt (-2.0 * log (w) / w);
y1 = x1 * w;
y2 = x2 * w;
}
pass = !pass;
return ( (y1 * s + (float) m));
}
6 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Gaussian White Noise
References : Posted by remage[AT]netposta.hu
Notes : SOURCE:
Steven W. Smith:
The Scientist and Engineer's Guide to Digital Signal Processing
http://www.dspguide.com
Code : #define PI 3.1415926536f
float R1 = (float) rand() / (float) RAND_MAX;
float R2 = (float) rand() / (float) RAND_MAX;
float X = (float) sqrt( -2.0f * log( R1 )) * cos( 2.0f * PI * R2 );
1 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Generator
Type : antialiased sawtooth References : Posted by Paul Sernine
Notes : This code generates a swept antialiasing sawtooth in a raw 16bit pcm file.
It is based on the quad differentiation of a 5th order polynomial. The polynomial harmonics (and aliased harmonics) decay at 5*6 dB per oct. The differenciators correct the spectrum and waveform, while aliased harmonics are still attenuated.
Code : /* clair.c Examen Partiel 2b
T.Rochebois
02/03/98
*/
#include <stdio.h>
#include <math.h>
main()
{
double phase=0,dphase,freq,compensation;
double aw0=0,aw1=0,ax0=0,ax1=0,ay0=0,ay1=0,az0=0,az1=0,sortie;
short aout;
int sr=44100; //sample rate (Hz)
double f_debut=55.0;//start freq (Hz)
double f_fin=sr/6.0;//end freq (Hz)
double octaves=log(f_fin/f_debut)/log(2.0);
double duree=50.0; //duration (s)
int i;
FILE* f;
f=fopen("saw.pcm","wb");
for(i=0;i<duree*sr;i++)
{
//exponential frequency sweep
//Can be replaced by anything you like.
freq=f_debut*pow(2.0,octaves*i/(duree*sr));
dphase=freq*(2.0/sr); //normalised phase increment
phase+=dphase; //phase incrementation
if(phase>1.0) phase-=2.0; //phase wrapping (-1,+1)
//polynomial calculation (extensive continuity at -1 +1)
// 7 1 3 1 5
//P(x) = --- x - -- x + --- x
// 360 36 120
aw0=phase*(7.0/360.0 + phase*phase*(-1/36.0 + phase*phase*(1/120.0)));
// quad differentiation (first order high pass filters)
ax0=aw1-aw0; ay0=ax1-ax0; az0=ay1-ay0; sortie=az1-az0;
//compensation of the attenuation of the quad differentiator
//this can be calculated at "control rate" and linearly
//interpolated at sample rate.
compensation=1.0/(dphase*dphase*dphase*dphase);
// compensation and output
aout=(short)(15000.0*compensation*sortie);
fwrite(&aout,1,2,f);
//old memories of differentiators
aw1=aw0; ax1=ax0; ay1=ay0; az1=az0;
}
fclose(f);
}
4 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Inverted parabolic envelope
Type : envellope generation References : Posted by James McCartney Code : dur = duration in samples
midlevel = amplitude at midpoint
beglevel = beginning and ending level (typically zero)
amp = midlevel - beglevel;
rdur = 1.0 / dur;
rdur2 = rdur * rdur;
level = beglevel;
slope = 4.0 * amp * (rdur - rdur2);
curve = -8.0 * amp * rdur2;
...
for (i=0; i<dur; ++i) {
level += slope;
slope += curve;
}
3 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
matlab/octave code for minblep table generation
References : Posted by dfl[at]ccrma[dot]stanford[dot]edu
Notes : When I tested this code, it was running with each function in a separate file... so it might need some tweaking (endfunction statements?) if you try and run it all as one file.
Enjoy!
PS There's a C++ version by Daniel Werner here.
http://www.experimentalscene.com/?type=2&id=1
Not sure if it the output is any different than my version.
(eg no thresholding in minphase calculation)
Code : % Octave/Matlab code to generate a minblep table for bandlimited synthesis
%% original minblep technique described by Eli Brandt:
%% http://www.cs.cmu.edu/~eli/L/icmc01/hardsync.html
% (c) David Lowenfels 2004
% you may use this code freely to generate your tables,
% but please send me a free copy of the software that you
% make with it, or at least send me an email to say hello
% and put my name in the software credits :)
% (IIRC: mps and clipdb functions are from Julius Smith)
% usage:
% fc = dilation factor
% Nzc = number of zero crossings
% omega = oversampling factor
% thresh = dB threshold for minimum phase calc
mbtable = minblep( fc, Nzc, omega, thresh );
mblen = length( mbtable );
save -binary mbtable.mat mbtable ktable nzc mblen;
*********************************************
function [out] = minblep( fc, Nzc, omega, thresh )
out = filter( 1, [1 -1], minblip( fc, Nzc, omega, thresh ) );
len = length( out );
normal = mean( out( floor(len*0.7):len ) )
out = out / normal; %% normalize
%% now truncate so it ends at proper phase cycle for minimum discontinuity
thresh = 1e-6;
for i = len:-1:len-1000
% pause
a = out(i) - thresh - 1;
b = out(i-1) - thresh - 1;
% i
if( (abs(a) < thresh) & (a > b) )
break;
endif
endfor
%out = out';
out = out(1:i);
*********************************************
function [out] = minblip( fc, Nzc, omega, thresh )
if (nargin < 4 )
thresh = -100;
end
if (nargin < 3 )
omega = 64;
end
if (nargin < 2 )
Nzc = 16;
end
if (nargin < 1 )
fc = 0.9;
end
blip = sinctable( omega, Nzc, fc );
%% length(blip) must be nextpow2! (if fc < 1 );
mag = fft( blip );
out = real( ifft( mps( mag, thresh ) ) );
*********************************************
function [sm] = mps(s, thresh)
% [sm] = mps(s)
% create minimum-phase spectrum sm from complex spectrum s
if (nargin < 2 )
thresh = -100;
endif
s = clipdb(s, thresh);
sm = exp( fft( fold( ifft( log( s )))));
*********************************************
function [clipped] = clipdb(s,cutoff)
% [clipped] = clipdb(s,cutoff)
% Clip magnitude of s at its maximum + cutoff in dB.
% Example: clip(s,-100) makes sure the minimum magnitude
% of s is not more than 100dB below its maximum magnitude.
% If s is zero, nothing is done.
as = abs(s);
mas = max(as(:));
if mas==0, return; end
if cutoff >= 0, return; end
thresh = mas*10^(cutoff/20); % db to linear
toosmall = find(as < thresh);
clipped = s;
clipped(toosmall) = thresh;
*********************************************
function [out, phase] = sinctable( omega, Nzc, fc )
if (nargin < 3 )
fc = 1.0 %% cutoff frequency
end %if
if (nargin < 2 )
Nzc = 16 %% number of zero crossings
end %if
if (nargin < 1 )
omega = 64 %% oversampling factor
end %if
Nzc = Nzc / fc %% This ensures more flatness at the ends.
phase = linspace( -Nzc, Nzc, Nzc*omega*2 );
%sinc = sin( pi * fc * phase) ./ (pi * fc * phase);
num = sin( pi*fc*phase );
den = pi*fc*phase;
len = length( phase );
sinc = zeros( len, 1 );
%sinc = num ./ den;
for i=1:len
if ( den(i) ~= 0 )
sinc(i) = num(i) / den(i);
else
sinc(i) = 1;
end
end %for
out = sinc;
window = blackman( len );
out = out .* window;
no comments on this item | add a comment | nofrills version |
|
 |
|
|
|
 |
PADsynth synthesys method
Type : wavetable generation References : Posted by zynaddsubfx[at]yahoo[dot]com
Notes : Please see the full description of the algorithm with public domain c++ code here:
http://zynaddsubfx.sourceforge.net/doc/PADsynth/PADsynth.htm
Code : It's here:
http://zynaddsubfx.sourceforge.net/doc/PADsynth/PADsynth.htm
You may copy it (everything is public domain).
Paul
3 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Parabolic shaper
References : Posted by azertopia at free dot fr
Notes : This function can be used for oscillators or shaper.
it can be driven by a phase accumulator or an audio input.
Code : Function Parashape(inp:single):single;
var fgh,tgh:single;
begin
fgh := inp ;
fgh := 0.25-f_abs(fgh) ;
tgh := fgh ;
tgh := 1-2*f_abs(tgh);
fgh := fgh*8;
result := fgh*tgh ;
end;
// f_abs is the function of ddsputils unit.
no comments on this item | add a comment | nofrills version |
|
 |
|
|
|
 |
Phase modulation Vs. Frequency modulation II
References : Posted by James McCartney
Notes : The difference between FM & PM in a digital oscillator is that FM is added to the frequency before the phase integration, while PM is added to the phase after the phase integration. Phase integration is when the old phase for the oscillator is added to the current frequency (in radians per sample) to get the new phase for the oscillator. The equivalent PM modulator to obtain the same waveform as FM is the integral of the FM modulator. Since the integral of sine waves are inverted cosine waves this is no problem. In modulators with multiple partials, the equivalent PM modulator will have different relative partial amplitudes. For example, the integral of a square wave is a triangle wave; they have the same harmonic content, but the relative partial amplitudes are different. These differences make no difference since we are not trying to exactly recreate FM, but real (or nonreal) instruments.
The reason PM is better is because in PM and FM there can be non-zero energy produced at 0 Hz, which in FM will produce a shift in pitch if the FM wave is used again as a modulator, however in PM the DC component will only produce a phase shift. Another reason PM is better is that the modulation index (which determines the number of sidebands produced and which in normal FM is calculated as the modulator amplitude divided by frequency of modulator) is not dependant on the frequency of the modulator, it is always equal to the amplitude of the modulator in radians. The benefit of solving the DC frequency shift problem, is that cascaded carrier-modulator pairs and feedback modulation are possible. The simpler calculation of modulation index makes it easier to have voices keep the same harmonic structure throughout all pitches.
The basic mathematics of phase modulation are available in any text on electronic communication theory.
Below is some C code for a digital oscillator that implements FM,PM,and AM. It illustrates the difference in implementation of FM & PM. It is only meant as an example, and not as an efficient implementation.
Code : /* Example implementation of digital oscillator with FM, PM, & AM */
#define PI 3.14159265358979
#define RADIANS_TO_INDEX (512.0 / (2.0 * PI))
typedef struct{ /* oscillator data */
double freq; /* oscillator frequency in radians per sample */
double phase; /* accumulated oscillator phase in radians */
double wavetable[512]; /* waveform lookup table */
} OscilRec;
/* oscil - compute 1 sample of oscillator output whose freq. phase and
* wavetable are in the OscilRec structure pointed to by orec.
*/
double oscil(orec, fm, pm, am)
OscilRec *orec; /* pointer to the oscil's data */
double fm; /* frequency modulation input in radians per sample */
double pm; /* phase modulation input in radians */
double am; /* amplitude modulation input in any units you want */
{
long tableindex; /* index into wavetable */
double instantaneous_freq; /* oscillator freq + freq modulation */
double instantaneous_phase; /* oscillator phase + phase modulation */
double output; /* oscillator output */
instantaneous_freq = orec->freq + fm; /* get instantaneous freq */
orec->phase += instantaneous_freq; /* accumulate phase */
instantaneous_phase = orec->phase + pm; /* get instantaneous phase */
/* convert to lookup table index */
tableindex = RADIANS_TO_INDEX * instantaneous_phase;
tableindex &= 511; /* make it mod 512 === eliminate multiples of 2*k*PI */
output = orec->wavetable[tableindex] * am; /* lookup and mult by am input */
return (output); /* return oscillator output */
}
1 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
PRNG for non-uniformly distributed values from trigonometric identity
Type : pseudo-random number generator References : Posted by neolit123 gmail com
Notes : a method, which generates random numbers in the [-1,+1] range, while having a probability density function with less concentration of values near zero for sin().
you can use an approximation of sin() and/or experiment with such an equation for different distributions. using tan() will accordingly invert the pdf graph i.e. more concentration near zero, but the output range will be also affected.
extended read on similar methods:
http://www.stat.wisc.edu/~larget/math496/random2.html
regards
lubomir
Code : //init
x=y=1;
//sampleloop
y=sin((x+=1)*y);
no comments on this item | add a comment | nofrills version |
|
 |
|
|
|
 |
Pseudo-Random generator
Type : Linear Congruential, 32bit References : Hal Chamberlain, "Musical Applications of Microprocessors" (Posted by Phil Burk)
Notes : This can be used to generate random numeric sequences or to synthesise a white noise audio signal.
If you only use some of the bits, use the most significant bits by shifting right.
Do not just mask off the low bits.
Code : /* Calculate pseudo-random 32 bit number based on linear congruential method. */
unsigned long GenerateRandomNumber( void )
{
/* Change this for different random sequences. */
static unsigned long randSeed = 22222;
randSeed = (randSeed * 196314165) + 907633515;
return randSeed;
}
no comments on this item | add a comment | nofrills version |
|
 |
|
|
|
 |
PulseQuad
Type : Waveform References : Posted by am[AT]andre-michelle[DOT]com
Notes : This is written in Actionscript 3.0 (Flash9). You can listen to the example at http://lab.andre-michelle.com/playing-with-pulse-harmonics
It allows to morph between a sinus like quadratic function and an ordinary pulse width with adjustable pulse width. Note that the slope while morphing is always zero at the edge points of the waveform. It is not just distorsion.
Code : http://lab.andre-michelle.com/swf/f9/pulsequad/PulseQuad.as
no comments on this item | add a comment | nofrills version |
|
 |
|
|
|
 |
Pulsewidth modulation
Type : waveform generation References : Steffan Diedrichsen
Notes : Take an upramping sawtooth and its inverse, a downramping sawtooth. Adding these two waves with a well defined delay between 0 and period (1/f)
results in a square wave with a duty cycle ranging from 0 to 100%.
no comments on this item | add a comment | nofrills version |
|
 |
|
|
|
 |
Quick & Dirty Sine
Type : Sine Wave Synthesis References : Posted by MisterToast
Notes : This is proof of concept only (but code works--I have it in my synth now).
Note that x must come in as 0<x<=4096. If you want to scale it to something else (like 0<x<=2*M_PI), do it in the call. Or do the math to scale the constants properly.
There's not much noise in here. A few little peaks here and there. When the signal is at -20dB, the worst noise is at around -90dB.
For speed, you can go all floats without much difference. You can get rid of that unitary negate pretty easily, as well. A couple other tricks can speed it up further--I went for clarity in the code.
The result comes out a bit shy of the range -1<x<1. That is, the peak is something like 0.999.
Where did this come from? I'm experimenting with getting rid of my waveform tables, which require huge amounts of memory. Once I had the Hamming anti-ringing code in, it looked like all my waveforms were smooth enough to approximate with curves. So I started with sine. Pulled my table data into Excel and then threw the data into a curve-fitting application.
This would be fine for a synth. The noise is low enough that you could easily get away with it. Ideal for a low-memory situation. My final code will be a bit harder to understand, as I'll break the curve up and curve-fit smaller sections.
Code : float xSin(double x)
{
//x is scaled 0<=x<4096
const double A=-0.015959964859;
const double B=217.68468676;
const double C=0.000028716332164;
const double D=-0.0030591066066;
const double E=-7.3316892871734489e-005;
double y;
bool negate=false;
if (x>2048)
{
negate=true;
x-=2048;
}
if (x>1024)
x=2048-x;
if (negate)
y=-((A+x)/(B+C*x*x)+D*x-E);
else
y=(A+x)/(B+C*x*x)+D*x-E;
return (float)y;
}
4 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
quick and dirty sine generator
Type : sine generator References : Posted by couriervst[AT]hotmail[DOT]com
Notes : this is part of my library, although I've seen a lot of sine generators, I've never seen the simplest one, so I try to do it,
tell me something, I've try it and work so tell me something about it
Code : PSPsample PSPsin1::doOsc(int numCh)
{
double x=0;
double t=0;
if(m_time[numCh]>m_sampleRate) //re-init cycle
m_time[numCh]=0;
if(m_time[numCh]>0)
{
t =(double)(((double)m_time[numCh])/(double)m_sampleRate);
x=(m_2PI *(double)(t)*m_freq);
}
else
x=0;
PSPsample r=(PSPsample) sin(x+m_phase)*m_amp;
m_time[numCh]++;
return r;
}
5 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
randja compressor
Type : compressor References : Posted by randja
Notes : I had found this code on the internet then made some improvements (speed) and now I post it here for others to see.
Code : #include <cmath>
#define max(a,b) (a>b?a:b)
class compressor
{
private:
float threshold;
float attack, release, envelope_decay;
float output;
float transfer_A, transfer_B;
float env, gain;
public:
compressor()
{
threshold = 1.f;
attack = release = envelope_decay = 0.f;
output = 1.f;
transfer_A = 0.f;
transfer_B = 1.f;
env = 0.f;
gain = 1.f;
}
void set_threshold(float value)
{
threshold = value;
transfer_B = output * pow(threshold,-transfer_A);
}
void set_ratio(float value)
{
transfer_A = value-1.f;
transfer_B = output * pow(threshold,-transfer_A);
}
void set_attack(float value)
{
attack = exp(-1.f/value);
}
void et_release(float value)
{
release = exp(-1.f/value);
envelope_decay = exp(-4.f/value); /* = exp(-1/(0.25*value)) */
}
void set_output(float value)
{
output = value;
transfer_B = output * pow(threshold,-transfer_A);
}
void reset()
{
env = 0.f; gain = 1.f;
}
__forceinline void process(float *input_left, float *input_right,float *output_left, float *output_right, int frames)
{
float det, transfer_gain;
for(int i=0; i<frames; i++)
{
det = max(fabs(input_left[i]),fabs(input_right[i]));
det += 10e-30f; /* add tiny DC offset (-600dB) to prevent denormals */
env = det >= env ? det : det+envelope_decay*(env-det);
transfer_gain = env > threshold ? pow(env,transfer_A)*transfer_B:output;
gain = transfer_gain < gain ?
transfer_gain+attack *(gain-transfer_gain):
transfer_gain+release*(gain-transfer_gain);
output_left[i] = input_left[i] * gain;
output_right[i] = input_right[i] * gain;
}
}
__forceinline void process(double *input_left, double *input_right, double *output_left, double *output_right,int frames)
{
double det, transfer_gain;
for(int i=0; i<frames; i++)
{
det = max(fabs(input_left[i]),fabs(input_right[i]));
det += 10e-30f; /* add tiny DC offset (-600dB) to prevent denormals */
env = det >= env ? det : det+envelope_decay*(env-det);
transfer_gain = env > threshold ? pow(env,transfer_A)*transfer_B:output;
gain = transfer_gain < gain ?
transfer_gain+attack *(gain-transfer_gain):
transfer_gain+release*(gain-transfer_gain);
output_left[i] = input_left[i] * gain;
output_right[i] = input_right[i] * gain;
}
}
};
3 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Rossler and Lorenz Oscillators
Type : Chaotic LFO References : Posted by kaleja[AT]estarcion[DOT]com
Notes : The Rossler and Lorenz functions are iterated chaotic systems - they trace smooth curves that never repeat the same way twice. Lorenz is "unpitched", having no distinct peaks in its spectrum -- similar to pink noise. Rossler exhibits definite spectral peaks against a noisy broadband background.
Time-domain and frequency spectrum of these two functions, as well as other info, can be found at:
http://www.physics.emory.edu/~weeks/research/tseries1.html
These functions might be useful in simulating "analog drift."
Code : Available on the web at:
http://www.tinygod.com/code/BLorenzOsc.zip
1 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
SawSin
Type : Oscillator shape References : Posted by Alexander Kritov Code : double sawsin(double x)
{
double t = fmod(x/(2*M_PI),(double)1.0);
if (t>0.5)
return -sin(x);
if (t<=0.5)
return (double)2.0*t-1.0;
}
no comments on this item | add a comment | nofrills version |
|
 |
|
|
|
 |
Simple Time Stretching-Granular Synthesizer
References : Posted by Harry-Chris
Notes : Matlab function that implements crude time stretching - granulizing function, by overlap add in time domain.
Code : function y = gran_func(x, w, H,H2, Fs, tr_amount)
% x -> input signal
% w -> Envelope - Window Vector
% H1 -> Original Hop Size
% H2 -> Synthesis Hop Size
% Fs -> Sample Rate
% str_amount -> time stretching factor
M = length(w);
pin = 1;
pend = length(x) - M;
y = zeros(1, floor( str_amount * length(x)) +M);
count = 1;
idx = 1;
while pin < pend
input = x(pin : pin+M-1) .* w';
y(idx : idx + M - 1) = y(idx : idx + M - 1) + input;
pin = pin + H;
count = count + 1;
idx = idx + H2;
end
no comments on this item | add a comment | nofrills version |
|
 |
|
|
|
 |
Sine calculation
Type : waveform generation, Taylor approximation of sin() References : Posted by Phil Burk
Notes : Code from JSyn for a sine wave generator based on a Taylor Expansion. It is not as efficient as the filter methods, but it has linear frequency control and is, therefore, suitable for FM or other time varying applications where accurate frequency is needed. The sine generated is accurate to at least 16 bits.
Code : for(i=0; i < nSamples ; i++)
{
//Generate sawtooth phasor to provide phase for sine generation
IncrementWrapPhase(phase, freqPtr[i]);
//Wrap phase back into region where results are more accurate
if(phase > 0.5)
yp = 1.0 - phase;
else
{
if(phase < -0.5)
yp = -1.0 - phase;
else
yp = phase;
}
x = yp * PI;
x2 = x*x;
//Taylor expansion out to x**9/9! factored into multiply-adds
fastsin = x*(x2*(x2*(x2*(x2*(1.0/362880.0)
- (1.0/5040.0))
+ (1.0/120.0))
- (1.0/6.0))
+ 1.0);
outPtr[i] = fastsin * amplPtr[i];
}
1 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Smooth random LFO Generator
References : Posted by Rob Belcham
Notes : I've been after a random LFO that's suitable for modulating a delay line for ages ( e.g for chorus / reverb modulation) , so after i rolled my own, i thought i'd better make it my first contribution to the music-dsp community.
My aim was to achive a sinusoidal based random but smooth waveform with a frequency control that has no discontinuities and stays within a -1:1 range. If you listen to it, it sounds quite like brown noise, or wind through a microphone (at rate = 100Hz for example)
It's written as a matlab m function, so shouldn't be too hard to port to C.
The oscillator generates a random level stepped waveform with random time spent at each step (within bounds). These levels are linearly interpolated between and used to drive the frequency of a sinewave. To achive amplitude variation, at each zero crossing a new random amplitude scale factor is generated. The amplitude coefficient is ramped to this value with a simple exponential.
An example call would be,
t = 4; Fs = 44100;
y = random_lfo(100, t*Fs, Fs);
axis([0, t*Fs, -1, 1]);
plot(y)
Enjoy !
Code : % Random LFO Generator
% creates a random sinusoidal waveform with no discontinuities
% rate = average rate in Hz
% N = run length in samples
% Fs = sample frequency in Hz
function y = random_lfo(rate, N, Fs)
step_freq_scale = Fs / (1*rate);
min_Cn = 0.1 * step_freq_scale;
An = 0;
lastA = 0;
Astep = 0;
y = zeros(1,N); % output
x = 0; % sine phase
lastSign = 0;
amp_scale = 0.6;
new_amp_scale = 0.6;
amp_scale_ramp = exp(1000/Fs)-1;
for (n=1:N)
if (An == 0) || (An>=Cn)
% generate a new random freq scale factor
Cn = floor(step_freq_scale * rand());
% limit to prevent rapid transitions
Cn = max(Cn, min_Cn);
% generate new value & step coefficient
newA = 0.1 + 0.9*rand();
Astep = (newA - lastA) / Cn;
A = lastA;
lastA = newA;
% reset counter
An = 0;
end
An = An + 1;
% generate output
y(n) = sin(x) * amp_scale;
% ramp amplitude
amp_scale = amp_scale + ( new_amp_scale - amp_scale ) * amp_scale_ramp;
sin_inc = 2*pi*rate*A/Fs;
A = A + Astep;
% increment phase
x = x + sin_inc;
if (x >= 2*pi)
x = x - 2*pi;
end
% scale at each zero crossing
if (sign(y(n)) ~= 0) && (sign(y(n)) ~= lastSign)
lastSign = sign(y(n));
new_amp_scale = 0.25 + 0.75*rand();
end;
end;
no comments on this item | add a comment | nofrills version |
|
 |
|
|
|
 |
Square Waves
Type : waveform generation References : Posted by Sean Costello
Notes : One way to do a square wave:
You need two buzz generators (see Dodge & Jerse, or the Csound source code, for implementation details). One of the buzz generators runs at the desired square wave frequency, while the second buzz generator is exactly one octave above this pitch. Subtract the higher octave buzz generator's output from the lower buzz generator's output - the result should be a signal with all odd harmonics, all at equal amplitude. Filter the resultant signal (maybe integrate it). Voila, a bandlimited square wave! Well, I think it should work...
The one question I have with the above technique is whether it produces a waveform that truly resembles a square wave in the time domain. Even if the number of harmonics, and the relative ratio of the harmonics, is identical to an "ideal" bandwidth-limited square wave, it may have an entirely different waveshape. No big deal, unless the signal is processed by a nonlinearity, in which case the results of the nonlinear processing will be far different than the processing of a waveform that has a similar shape to a square wave.
2 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Trammell Pink Noise (C++ class)
Type : pink noise generator References : Posted by dfl at ccrma dot stanford dot edu Code : #ifndef _PinkNoise_H
#define _PinkNoise_H
// Technique by Larry "RidgeRat" Trammell 3/2006
// http://home.earthlink.net/~ltrammell/tech/pinkalg.htm
// implementation and optimization by David Lowenfels
#include <cstdlib>
#include <ctime>
#define PINK_NOISE_NUM_STAGES 3
class PinkNoise {
public:
PinkNoise() {
srand ( time(NULL) ); // initialize random generator
clear();
}
void clear() {
for( size_t i=0; i< PINK_NOISE_NUM_STAGES; i++ )
state[ i ] = 0.0;
}
float tick() {
static const float RMI2 = 2.0 / float(RAND_MAX); // + 1.0; // change for range [0,1)
static const float offset = A[0] + A[1] + A[2];
// unrolled loop
float temp = float( rand() );
state[0] = P[0] * (state[0] - temp) + temp;
temp = float( rand() );
state[1] = P[1] * (state[1] - temp) + temp;
temp = float( rand() );
state[2] = P[2] * (state[2] - temp) + temp;
return ( A[0]*state[0] + A[1]*state[1] + A[2]*state[2] )*RMI2 - offset;
}
protected:
float state[ PINK_NOISE_NUM_STAGES ];
static const float A[ PINK_NOISE_NUM_STAGES ];
static const float P[ PINK_NOISE_NUM_STAGES ];
};
const float PinkNoise::A[] = { 0.02109238, 0.07113478, 0.68873558 }; // rescaled by (1+P)/(1-P)
const float PinkNoise::P[] = { 0.3190, 0.7756, 0.9613 };
#endif
2 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Waveform generator using MinBLEPS
References : Posted by locke[AT]rpgfan.demon.co.uk Linked file : MinBLEPS.zip
Notes : C code and project file for MSVC6 for a bandwidth-limited saw/square (with PWM) generator using MinBLEPS.
This code is based on Eli's MATLAB MinBLEP code and uses his original minblep.mat file.
Instead of keeping a list of all active MinBLEPS, the output of each MinBLEP is stored in a buffer, in which all consequent MinBLEPS and the waveform output are added together. This optimization makes it fast enough to be used realtime.
Produces slight aliasing when sweeping high frequencies. I don't know wether Eli's original code does the same, because I don't have MATLAB. Any help would be appreciated.
The project name is 'hardsync', because it's easy to generate hardsync using MinBLEPS.
Code :
3 comment(s) | add a comment | nofrills version |
|
 |
|
|
|
 |
Weird synthesis
References : Posted by Andy M00cho
Notes : (quoted from Andy's mail...)
What I've done in a soft-synth I've been working on is used what I've termed Fooglers, no reason, just liked the name :) Anyway all I've done is use a *VERY* short delay line of 256 samples and then use 2 controllable taps into the delay with High Frequency Damping, and a feedback parameter.
Using a tiny fixed delay size of approx. 4.8ms (really 256 samples/1k memory with floats) means this costs, in terms of cpu consumption practically nothing, and the filter is a real simple 1 pole low-pass filter. Maybe not DSP'litically correct but all I wanted was to avoid the high frequencies trashing the delay line when high feedbacks (99%->99.9%) are used (when the fun starts ;).
I've been getting some really sexy sounds out of this idea, and of course you can have the delay line tuneable if you choose to use fractional taps, but I'm happy with it as it is.. 1 nice simple, yet powerful addition to the base oscillators.
In reality you don't need 2 taps, but I found that using 2 added that extra element of funkiness...
2 comment(s) | add a comment | nofrills version |
|
 |
|
|
|