shithub: leaf

Download patch

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));
 }