|
|
|
|
 |
(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];
}
no comments on this item | 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));
--------------
1 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.
1 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...
4 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
6 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)
1 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);
1 comment(s) | 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;
}
no comments on this item | 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
}
1 comment(s) | 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;
}
4 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 |
|
 |
|
|
|
|
|
 |
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.
1 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
1 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;
1 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));
}
1 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 |
|
 |
|
|
|
|
|
 |
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;
}
2 comment(s) | 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 */
}
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 |
|
 |
|
|
|
|
|
 |
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 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;
}
2 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 |
|
 |
|
|
|
|
|
 |
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 |
|
 |
|
|
|
|
|
 |
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.
1 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 :
1 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 |
|
 |
|
|
|
|