Skip to content

Commit f6607e6

Browse files
* Add local state data to Oscillator
- Need to find a better way to do that... * Noise oscillator generates colored noise - Inspired by Dave Smith Instruments Prophet-12 - Controlled by Width parameter - 0%: red noise (-6dB/octave) - 25%: pink noise (-3dB/octave) - 50%: white noise (0dB/octave) - 75%: blue noise (+3dB/octave) - 100%: violet noise (+6dB/octave)
1 parent b8362d2 commit f6607e6

File tree

3 files changed

+168
-4
lines changed

3 files changed

+168
-4
lines changed

Oscillator.cpp

+21-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ void OscillatorState::Reset()
1515
{
1616
phase = 0.0f;
1717
index = 0;
18+
memset(f, 0, sizeof(f));
1819
}
1920

2021
// start oscillator
@@ -26,9 +27,6 @@ void OscillatorState::Start()
2627
// update oscillator
2728
float OscillatorState::Update(OscillatorConfig const &config, float const step)
2829
{
29-
if (!config.enable)
30-
return 0.0f;
31-
3230
float const delta = config.frequency * config.adjust * step;
3331

3432
// compute oscillator value
@@ -50,6 +48,25 @@ float OscillatorState::Compute(OscillatorConfig const &config, float delta)
5048
void OscillatorState::Advance(OscillatorConfig const &config, float delta)
5149
{
5250
phase += delta;
51+
#if 1
52+
if (config.sync_enable)
53+
{
54+
if (phase >= config.sync_phase - index)
55+
{
56+
phase -= config.sync_phase - index;
57+
index = 0;
58+
}
59+
}
60+
else
61+
{
62+
int const advance = FloorInt(phase);
63+
if (advance)
64+
{
65+
phase -= advance;
66+
index += advance;
67+
}
68+
}
69+
#else
5370
if (phase >= config.sync_phase)
5471
{
5572
// wrap phase around
@@ -74,4 +91,5 @@ void OscillatorState::Advance(OscillatorConfig const &config, float delta)
7491
if (index < 0)
7592
index += cycle;
7693
}
94+
#endif
7795
}

Oscillator.h

+7
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ class OscillatorState
5656
float phase;
5757
int index;
5858

59+
// state values usable by wave functions
60+
union
61+
{
62+
float f[8];
63+
int i[8];
64+
};
65+
5966
OscillatorState()
6067
{
6168
Reset();

WaveNoise.cpp

+140-1
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,148 @@ White Noise
88

99
#include "Random.h"
1010
#include "WaveNoise.h"
11+
#include "Oscillator.h"
12+
#include "Math.h"
1113

12-
// white noise wave
14+
// http://www.firstpr.com.au/dsp/pink-noise/
15+
//b0 = 0.99765f * b0 + white * 0.0990460f; // x42.147234f
16+
//b1 = 0.96300f * b1 + white * 0.2965164f; // x8.013957f
17+
//b2 = 0.57000f * b2 + white * 1.0526913f; // x2.448119f
18+
//float const pink = 0.25f * (b0 + b1 + b2 + white * 0.1848f);
19+
20+
#define FILTERS 3
21+
22+
// low-pass filter bank for colored noise
23+
#if FILTERS == 3
24+
static const float a[3] =
25+
{
26+
1 - 0.997907817f, // 1 - expf(-2 * M_PI * 16 / 48000);
27+
1 - 0.967044930f, // 1 - expf(-2 * M_PI * 256 / 48000);
28+
1 - 0.584987297f, // 1 - expf(-2 * M_PI * 4096 / 48000);
29+
};
30+
static const float falloff = 0.25; // sqrtf(1.f / 16.0f)
31+
static float const w0 = 1 - falloff;
32+
static float const w1 = w0 * falloff;
33+
static float const w2 = w1 * falloff;
34+
static const float w3 = falloff - w1 - w2;
35+
#elif FILTERS == 4
36+
static const float a[4] =
37+
{
38+
1 - 0.997907817f, // 1 - expf(-2 * M_PI * 16 / 48000);
39+
1 - 0.983384430f, // 1 - expf(-2 * M_PI * 128 / 48000);
40+
1 - 0.874553978f, // 1 - expf(-2 * M_PI * 1024 / 48000);
41+
1 - 0.342210114f, // 1 - expf(-2 * M_PI * 8192 / 48000);
42+
};
43+
static const float falloff = 0.353553385f; // sqrtf(1.f / 8.f);
44+
static float const w0 = 1 - falloff;
45+
static float const w1 = w0 * falloff;
46+
static float const w2 = w1 * falloff;
47+
static float const w3 = w2 * falloff;
48+
static float const w4 = falloff - w1 - w2 - w3;
49+
#elif FILTERS == 5
50+
static const float a[5] =
51+
{
52+
1 - 0.997907817f, // 1 - expf(-2 * M_PI * 16 / 48000);
53+
1 - 0.991657414f, // 1 - expf(-2 * M_PI * 64 / 48000);
54+
1 - 0.967044930f, // 1 - expf(-2 * M_PI * 256 / 48000);
55+
1 - 0.874553978f, // 1 - expf(-2 * M_PI * 1024 / 48000);
56+
1 - 0.584987297f, // 1 - expf(-2 * M_PI * 4096 / 48000);
57+
};
58+
static const float falloff = 0.25f; //sqrtf(1.f / 4.f);
59+
static float const w0 = 1 - falloff;
60+
static float const w1 = w0 * falloff;
61+
static float const w2 = w1 * falloff;
62+
static float const w3 = w2 * falloff;
63+
static float const w4 = w3 * falloff;
64+
static float const w5 = falloff - w1 - w2 - w3 - w4;
65+
#endif
66+
67+
// noise wave
1368
float OscillatorNoise(OscillatorConfig const &config, OscillatorState &state, float step)
1469
{
70+
#if 1
71+
// whte noise
72+
float white = Random::Float() * 2.0f - 1.0f;
73+
74+
// if generating pure white noise, return that
75+
if (config.waveparam == 0.5f)
76+
return white;
77+
78+
float param = config.waveparam;
79+
80+
// low-pass filter bank
81+
for (int i = 0; i < FILTERS; ++i)
82+
state.f[i] += (white - state.f[i]) * a[i];
83+
84+
85+
// desired spectral tilt:
86+
// param=0.00 red -6dB/oct
87+
// param=0.25 pink -3dB/oct,
88+
// param=0.50 white 0dB/oct
89+
// param=0.75 blue +3dB/oct
90+
// param=1.00 violet +6dB/oct
91+
92+
// if generating red/pink...
93+
if (config.waveparam < 0.5f)
94+
{
95+
// -3dB/oct pink noise
96+
#if FILTERS == 3
97+
float const pink = 8 * (w0 * state.f[0] + w1 * state.f[1] + w2 * state.f[2] + w3 * white);
98+
#elif FILTERS == 4
99+
float const pink = 8 * (w0 * state.f[0] + w1 * state.f[1] + w2 * state.f[2] + w3 * state.f[3] + w4 * white);
100+
#elif FILTERS == 5
101+
float const pink = 8 * (w0 * state.f[0] + w1 * state.f[1] + w2 * state.f[2] + w3 * state.f[3] + w2 * state.f[4] + w5 * white);
102+
#endif
103+
104+
// if generating pure pink noise, return that
105+
if (param == 0.25f)
106+
return pink;
107+
108+
if (param < 0.25)
109+
{
110+
// -6dB/oct red noise
111+
float const red = 16 * state.f[0];
112+
113+
// blend between red and pink
114+
float const s = param * 4;
115+
return red + (pink - red) * s;
116+
}
117+
else
118+
{
119+
// bend between white and pink
120+
float const s = param * 4 - 1;
121+
return pink + (white - pink) * s;
122+
}
123+
}
124+
else
125+
{
126+
// +3dB/oct blue noise
127+
#if FILTERS == 3
128+
float const blue = 2 * (white - w2 * state.f[0] - w1 * state.f[1] - w0 * state.f[2]);
129+
#elif FILTERS == 4
130+
float const blue = 2 * (white - w3 * state.f[0] - w2 * state.f[1] - w1 * state.f[2] - w0 * state.f[3]);
131+
#elif FILTERS == 5
132+
float const blue = 2 * (white - w4 * state.f[0] - w3 * state.f[1] - w2 * state.f[2] - w1 * state.f[3] - w0 * state.f[4]);
133+
#endif
134+
135+
if (param < 0.75f)
136+
{
137+
// blend between white and blue
138+
float const s = param * 4 - 2;
139+
return white + (blue - white) * s;
140+
}
141+
else
142+
{
143+
// +6dB/oct violet noise
144+
float const violet = 1.41421356f *(white - state.f[FILTERS]);
145+
state.f[FILTERS] = white;
146+
147+
// blend between blue and violet
148+
float const s = param * 4 - 3;
149+
return blue + (violet - blue) * s;
150+
}
151+
}
152+
#else
15153
return Random::Float() * 2.0f - 1.0f;
154+
#endif
16155
}

0 commit comments

Comments
 (0)