ref: f3bfe55e7d09ae5b44221279f481575fe74b5a2a
parent: 4fa07020d3c13de61a71d7d4730e059741935799
author: Jeff Snyder <jeff@snyderphonics.com>
date: Thu Sep 26 15:40:15 EDT 2019
more generalized WDF implementation
--- a/LEAF/Inc/leaf-WDF.h
+++ b/LEAF/Inc/leaf-WDF.h
@@ -8,8 +8,17 @@
#ifndef LEAF_INC_LEAF_WDF_H_
#define LEAF_INC_LEAF_WDF_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+//==============================================================================
+#include "leaf-globals.h"
+#include "leaf-math.h"
+
+//==============================================================================
+
//---
//WDF resistor
@@ -101,6 +110,67 @@
float tWDFseriesAdaptor_getReflectedWave(tWDFseriesAdaptor* const r);
float tWDFseriesAdaptor_getVoltage(tWDFseriesAdaptor* const r);
float tWDFseriesAdaptor_getCurrent(tWDFseriesAdaptor* const r);
+
+//WDF component
+typedef enum WDFComponentType
+{
+ SeriesAdaptor = 0,
+ ParallelAdaptor,
+ Resistor,
+ Capacitor,
+ ResistiveSource,
+ ComponentNil
+} WDFComponentType;
+
+typedef struct _tWDF tWDF; // needed to allow tWDF pointers in struct
+struct _tWDF
+{
+ WDFComponentType type;
+ float port_resistance_up;
+ float port_resistance_left;
+ float port_resistance_right;
+ float port_conductance_up;
+ float port_conductance_left;
+ float port_conductance_right;
+ float incident_wave_up;
+ float incident_wave_left;
+ float incident_wave_right;
+ float reflected_wave_up;
+ float reflected_wave_left;
+ float reflected_wave_right;
+ float gamma_zero;
+ float sample_rate;
+ float value;
+ tWDF* child_left;
+ tWDF* child_right;
+ float (*get_port_resistance)(tWDF* const);
+ float (*get_reflected_wave)(tWDF* const);
+ void (*set_incident_wave)(tWDF* const, float);
+};
+
+void tWDF_init(tWDF* const r, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR, float sample_rate);
+float tWDF_tick(tWDF* const r, float sample, uint8_t paramsChanged);
+void tWDF_setValue(tWDF* const r, float value);
+float tWDF_getPortResistance(tWDF* const r);
+void tWDF_setPortResistances(tWDF* const r);
+float tWDF_getReflectedWave(tWDF* const r);
+void tWDF_setIncidentWave(tWDF* const r, float incident_wave);
+float tWDF_getVoltage(tWDF* const r);
+float tWDF_getCurrent(tWDF* const r);
+
+static float get_port_resistance_for_resistor(tWDF* const r);
+static float get_port_resistance_for_capacitor(tWDF* const r);
+static float get_port_resistance_for_series(tWDF* const r);
+static float get_port_resistance_for_parallel(tWDF* const r);
+
+static void set_incident_wave_for_leaf(tWDF* const r, float incident_wave);
+static void set_incident_wave_for_series(tWDF* const r, float incident_wave);
+static void set_incident_wave_for_parallel(tWDF* const r, float incident_wave);
+
+static float get_reflected_wave_for_resistor(tWDF* const r);
+static float get_reflected_wave_for_capacitor(tWDF* const r);
+static float get_reflected_wave_for_series(tWDF* const r);
+static float get_reflected_wave_for_parallel(tWDF* const r);
--- a/LEAF/Src/leaf-WDF.c
+++ b/LEAF/Src/leaf-WDF.c
@@ -96,6 +96,7 @@
r->sample_rate = sample_rate;
r->memory = 0.0f;
}
+
float tWDFcapacitor_getPortResistance(tWDFcapacitor* const r)
{
return r->port_resistance;
@@ -177,4 +178,226 @@
float tWDFseriesAdaptor_getCurrent(tWDFseriesAdaptor* const r)
{
return (((r->incident_wave_up * 0.5f) - (r->reflected_wave_up * 0.5f)) * r->port_conductance_up);
+}
+
+//WDF
+
+void tWDF_init(tWDF* const r, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR, float sample_rate)
+{
+ r->type = type;
+ r->incident_wave_up = 0.0f;
+ r->incident_wave_left = 0.0f;
+ r->incident_wave_right = 0.0f;
+ r->reflected_wave_up = 0.0f;
+ r->reflected_wave_left = 0.0f;
+ r->reflected_wave_right = 0.0f;
+ r->sample_rate = sample_rate;
+ r->value = value;
+ if (r->type == SeriesAdaptor)
+ {
+ r->child_left = rL;
+ r->child_right = rR;
+ r->port_resistance_left = tWDF_getPortResistance(rL);
+ r->port_resistance_right = tWDF_getPortResistance(rR);
+ r->port_resistance_up = r->port_resistance_left + r->port_resistance_right;
+ r->port_conductance_up = 1.0f / r->port_resistance_up;
+ r->port_conductance_left = 1.0f / r->port_resistance_left;
+ r->port_conductance_right = 1.0f / r->port_resistance_right;
+ r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left);
+
+ r->get_port_resistance = &get_port_resistance_for_series;
+ r->get_reflected_wave = &get_reflected_wave_for_series;
+ r->set_incident_wave = &set_incident_wave_for_series;
+ }
+ else if (r->type == ParallelAdaptor)
+ {
+ r->child_left = rL;
+ r->child_right = rR;
+ r->port_resistance_left = tWDF_getPortResistance(rL);
+ r->port_resistance_right = tWDF_getPortResistance(rR);
+ r->port_resistance_up = (r->port_resistance_left * r->port_resistance_right) / (r->port_resistance_left + r->port_resistance_right);
+ r->port_conductance_up = 1.0f / r->port_resistance_up;
+ r->port_conductance_left = 1.0f / r->port_resistance_left;
+ r->port_conductance_right = 1.0f / r->port_resistance_right;
+ r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left);
+
+ r->get_port_resistance = &get_port_resistance_for_parallel;
+ r->get_reflected_wave = &get_reflected_wave_for_parallel;
+ r->set_incident_wave = &set_incident_wave_for_parallel;
+ }
+ else if (r->type == Resistor)
+ {
+ r->port_resistance_up = r->value;
+ r->port_conductance_up = 1.0f / r->value;
+
+ r->get_port_resistance = &get_port_resistance_for_resistor;
+ r->get_reflected_wave = &get_reflected_wave_for_resistor;
+ r->set_incident_wave = &set_incident_wave_for_leaf;
+ }
+ else if (r->type == Capacitor)
+ {
+ r->port_resistance_up = 1.0f / (sample_rate * 2.0f * r->value); //based on trapezoidal discretization
+ r->port_conductance_up = (1.0f / r->port_resistance_up);
+
+ r->get_port_resistance = &get_port_resistance_for_capacitor;
+ r->get_reflected_wave = &get_reflected_wave_for_capacitor;
+ r->set_incident_wave = &set_incident_wave_for_leaf;
+ }
+ else if (r->type == ResistiveSource)
+ {
+
+ }
+}
+
+float tWDF_tick(tWDF* const r, float sample, uint8_t paramsChanged)
+{
+ //step 0 : update port resistances if something changed
+ if (paramsChanged) tWDF_getPortResistance(r);
+
+ //step 1 : set inputs to what they should be
+ float input = sample;
+
+ //step 2 : scan the waves up the tree
+ float incident_wave = tWDF_getReflectedWave(r);
+
+ //step 3 : do root scattering computation
+ float reflected_wave = (2.0f * input) - incident_wave;
+
+ //step 4 : propigate waves down the tree
+ tWDF_setIncidentWave(r, reflected_wave);
+
+ //step 5 : grab whatever voltages or currents we want as outputs
+ return -1.0f * tWDF_getVoltage(r->child_right->child_right);
+}
+
+void tWDF_setValue(tWDF* const r, float value)
+{
+ r->value = value;
+}
+
+float tWDF_getPortResistance(tWDF* const r)
+{
+ return r->get_port_resistance(r);
+}
+
+void tWDF_setIncidentWave(tWDF* const r, float incident_wave)
+{
+ r->set_incident_wave(r, incident_wave);
+}
+
+float tWDF_getReflectedWave(tWDF* const r)
+{
+ return r->get_reflected_wave(r);
+}
+
+float tWDF_getVoltage(tWDF* const r)
+{
+ return ((r->incident_wave_up * 0.5f) + (r->reflected_wave_up * 0.5f));
+}
+
+float tWDF_getCurrent(tWDF* const r)
+{
+ return (((r->incident_wave_up * 0.5f) - (r->reflected_wave_up * 0.5f)) * r->port_conductance_up);
+}
+
+// static functions to be pointed to
+static float get_port_resistance_for_resistor(tWDF* const r)
+{
+ r->port_resistance_up = r->value;
+ r->port_conductance_up = 1.0f / r->value;
+
+ return r->port_resistance_up;
+}
+
+static float get_port_resistance_for_capacitor(tWDF* const r)
+{
+ r->port_resistance_up = 1.0f / (r->sample_rate * 2.0f * r->value); //based on trapezoidal discretization
+ r->port_conductance_up = (1.0f / r->port_resistance_up);
+
+ return r->port_resistance_up;
+}
+
+static float get_port_resistance_for_series(tWDF* const r)
+{
+ r->port_resistance_left = tWDF_getPortResistance(r->child_left);
+ r->port_resistance_right = tWDF_getPortResistance(r->child_right);
+ r->port_resistance_up = r->port_resistance_left + r->port_resistance_right;
+ r->port_conductance_up = 1.0f / r->port_resistance_up;
+ r->port_conductance_left = 1.0f / r->port_resistance_left;
+ r->port_conductance_right = 1.0f / r->port_resistance_right;
+ r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left);
+
+ return r->port_resistance_up;
+}
+
+static float get_port_resistance_for_parallel(tWDF* const r)
+{
+ r->port_resistance_left = tWDF_getPortResistance(r->child_left);
+ r->port_resistance_right = tWDF_getPortResistance(r->child_right);
+ r->port_resistance_up = (r->port_resistance_left * r->port_resistance_right) / (r->port_resistance_left + r->port_resistance_right);
+ r->port_conductance_up = 1.0f / r->port_resistance_up;
+ r->port_conductance_left = 1.0f / r->port_resistance_left;
+ r->port_conductance_right = 1.0f / r->port_resistance_right;
+ r->gamma_zero = 1.0f / (r->port_conductance_right + r->port_conductance_left);
+
+ return r->port_resistance_up;
+}
+
+static void set_incident_wave_for_leaf(tWDF* const r, float incident_wave)
+{
+ r->incident_wave_up = incident_wave;
+}
+
+static void set_incident_wave_for_series(tWDF* const r, float incident_wave)
+{
+ float gamma_left = r->port_resistance_left * r->gamma_zero;
+ float gamma_right = r->port_resistance_right * r->gamma_zero;
+ float left_wave = tWDF_getReflectedWave(r->child_left);
+ float right_wave = tWDF_getReflectedWave(r->child_right);
+// downPorts[0]->b = yl * ( downPorts[0]->a * ((1.0 / yl) - 1) - downPorts[1]->a - descendingWave );
+// downPorts[1]->b = yr * ( downPorts[1]->a * ((1.0 / yr) - 1) - downPorts[0]->a - descendingWave );
+ tWDF_setIncidentWave(r->child_left, (-1.0f * gamma_left * incident_wave) + (gamma_right * left_wave) - (gamma_left * right_wave));
+ tWDF_setIncidentWave(r->child_right, (-1.0f * gamma_right * incident_wave) + (gamma_left * right_wave) - (gamma_right * left_wave));
+ // From rt-wdf
+// tWDF_setIncidentWave(r->child_left, gamma_left * (left_wave * ((1.0f / gamma_left) - 1.0f) - right_wave - incident_wave));
+// tWDF_setIncidentWave(r->child_right, gamma_right * (right_wave * ((1.0f / gamma_right) - 1.0f) - left_wave - incident_wave));
+
+}
+
+static void set_incident_wave_for_parallel(tWDF* const r, float incident_wave)
+{
+ float gamma_left = r->port_conductance_left * r->gamma_zero;
+ float gamma_right = r->port_conductance_right * r->gamma_zero;
+ float left_wave = tWDF_getReflectedWave(r->child_left);
+ float right_wave = tWDF_getReflectedWave(r->child_right);
+// downPorts[0]->b = ( ( dl - 1 ) * downPorts[0]->a + dr * downPorts[1]->a + du * descendingWave );
+// downPorts[1]->b = ( dl * downPorts[0]->a + ( dr - 1 ) * downPorts[1]->a + du * descendingWave );
+ tWDF_setIncidentWave(r->child_left, (gamma_left - 1.0f) * left_wave + gamma_right * right_wave + incident_wave);
+ tWDF_setIncidentWave(r->child_right, gamma_left * left_wave + (gamma_right - 1.0f) * right_wave + incident_wave);
+}
+
+static float get_reflected_wave_for_resistor(tWDF* const r)
+{
+ r->reflected_wave_up = 0.0f;
+ return r->reflected_wave_up;
+}
+
+static float get_reflected_wave_for_capacitor(tWDF* const r)
+{
+ r->reflected_wave_up = r->incident_wave_up;
+ return r->reflected_wave_up;
+}
+
+static float get_reflected_wave_for_series(tWDF* const r)
+{
+ //-( downPorts[0]->a + downPorts[1]->a );
+ return (-1.0f * (tWDF_getReflectedWave(r->child_left) + tWDF_getReflectedWave(r->child_right)));
+}
+
+static float get_reflected_wave_for_parallel(tWDF* const r)
+{
+ float gamma_left = r->port_conductance_left * r->gamma_zero;
+ float gamma_right = r->port_conductance_right * r->gamma_zero;
+ //return ( dl * downPorts[0]->a + dr * downPorts[1]->a );
+ return (gamma_left * tWDF_getReflectedWave(r->child_left) + gamma_right * tWDF_getReflectedWave(r->child_right));
}