Explorar el Código

Ladder filter frequency modulation in "volts per octave"

dds
PaulStoffregen hace 3 años
padre
commit
8f0829c845
Se han modificado 3 ficheros con 51 adiciones y 9 borrados
  1. +15
    -4
      examples/Synthesis/LadderFilter/LadderFilter.ino
  2. +34
    -5
      filter_ladder.cpp
  3. +2
    -0
      filter_ladder.h

+ 15
- 4
examples/Synthesis/LadderFilter/LadderFilter.ino Ver fichero

@@ -3,6 +3,11 @@
// By Richard van Hoesel
// https://forum.pjrc.com/threads/60488?p=269756&viewfull=1#post269756

// Ladder filter demo with continuous 3-saw drone into the filter
// with separate LFOs modulating filter frequency and resonance.
// By Richard van Hoesel
// https://forum.pjrc.com/threads/60488?p=269756&viewfull=1#post269756

#include <Audio.h>

AudioSynthWaveform waveform1;
@@ -32,8 +37,9 @@ void setup() {
sgtl5000_1.enable();
sgtl5000_1.volume(0.6);

filter1.resonance(0.55);
filter1.frequency(4000);
filter1.resonance(0.55); // "lfo2" waveform overrides this setting
filter1.frequency(800); // "lfo1" modifies this 800 Hz setting
filter1.octaveControl(2.6); // up 2.6 octaves (4850 Hz) & down 2.6 octaves (132 Hz)
waveform1.frequency(50);
waveform2.frequency(100.1);
waveform3.frequency(150.3);
@@ -44,17 +50,22 @@ void setup() {
waveform2.begin(WAVEFORM_BANDLIMIT_SAWTOOTH);
waveform3.begin(WAVEFORM_BANDLIMIT_SAWTOOTH);
lfo1.frequency(0.2);
lfo1.amplitude(0.985);
lfo1.amplitude(0.99);
lfo1.phase(270);
lfo1.begin(WAVEFORM_TRIANGLE);
lfo2.frequency(0.07);
lfo2.amplitude(0.55);
lfo2.phase(270);
lfo2.begin(WAVEFORM_SINE);
}

void loop() {
Serial.print("CPU Usage: ");
Serial.print("Filter CPU Usage: ");
Serial.print(filter1.processorUsageMax());
Serial.print("%, Total CPU Usage: ");
Serial.print(AudioProcessorUsageMax());
Serial.println("%");
filter1.processorUsageMaxReset();
AudioProcessorUsageMaxReset();
delay(1000);
}

+ 34
- 5
filter_ladder.cpp Ver fichero

@@ -38,6 +38,7 @@
#define MOOG_PI ((float)3.14159265358979323846264338327950288)

#define MAX_RESONANCE ((float)1.1)
#define MAX_FREQUENCY ((float)(AUDIO_SAMPLE_RATE_EXACT * 0.49f))

float AudioFilterLadder::LPF(float s, int i)
{
@@ -65,10 +66,20 @@ void AudioFilterLadder::frequency(float c)
compute_coeffs(c);
}

void AudioFilterLadder::octaveControl(float octaves)
{
if (octaves > 7.0f) {
octaves = 7.0f;
} else if (octaves < 0.0f) {
octaves = 0.0f;
}
octaveScale = octaves / 32768.0f;
}

void AudioFilterLadder::compute_coeffs(float c)
{
if (c > 0.49f * AUDIO_SAMPLE_RATE_EXACT) {
c = 0.49f * AUDIO_SAMPLE_RATE_EXACT;
if (c > MAX_FREQUENCY) {
c = MAX_FREQUENCY;
} else if (c < 1.0f) {
c = 1.0f;
}
@@ -86,6 +97,24 @@ bool AudioFilterLadder::resonating()
return false;
}

static inline float fast_exp2f(float x)
{
float i;
float f = modff(x, &i);
f *= 0.693147f / 256.0f;
f += 1.0f;
f *= f;
f *= f;
f *= f;
f *= f;
f *= f;
f *= f;
f *= f;
f *= f;
f = ldexpf(f, i);
return f;
}

static inline float fast_tanh(float x)
{
float x2 = x * x;
@@ -128,9 +157,9 @@ void AudioFilterLadder::update(void)
for (int i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
float input = blocka->data[i] * (1.0f/32768.0f);
if (FCmodActive) {
float FCmod = blockb->data[i] * (1.0f/32768.0f);
// TODO: should this be "volts per octave"?
float ftot = Fbase + Fbase * FCmod;
float FCmod = blockb->data[i] * octaveScale;
float ftot = Fbase * fast_exp2f(FCmod);
if (ftot > MAX_FREQUENCY) ftot = MAX_FREQUENCY;
if (FCmod != 0) compute_coeffs(ftot);
}
if (QmodActive) {

+ 2
- 0
filter_ladder.h Ver fichero

@@ -42,6 +42,7 @@ public:
AudioFilterLadder() : AudioStream(3, inputQueueArray) {};
void frequency(float FC);
void resonance(float reson);
void octaveControl(float octaves);
virtual void update(void);
private:
float LPF(float s, int i);
@@ -53,6 +54,7 @@ private:
float z1[4] = {0.0, 0.0, 0.0, 0.0};
float K = 1.0;
float Fbase = 1000;
float octaveScale = 1.0f/32768.0f;
//float Qbase = 0.5;
//float overdrive = 1.0;
audio_block_t *inputQueueArray[3];

Cargando…
Cancelar
Guardar