| @@ -9,7 +9,6 @@ · 8 unmodified lines |
| 9 | #include "../Inc/leaf-WDF.h" | 9 | #include "../Inc/leaf-WDF.h" |
| 10 | | 10 | |
| 11 | //WDF | 11 | //WDF |
| 12 | | | |
| 13 | void tWDF_init(tWDF* const r, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR) | 12 | void tWDF_init(tWDF* const r, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR) |
| 14 | { | 13 | { |
| 15 | r->type = type; | 14 | r->type = type; |
| @@ -24,35 +23,7 @@ void tWDF_init(tWDF* const r, WDFComponentType type, float value, tWDF* const rL · 8 unmodified lines |
| 24 | r->reflected_wave_right = 0.0f; | 23 | r->reflected_wave_right = 0.0f; |
| 25 | r->sample_rate = leaf.sampleRate; | 24 | r->sample_rate = leaf.sampleRate; |
| 26 | r->value = value; | 25 | r->value = value; |
| 27 | if (r->type == SeriesAdaptor) | 26 | if (r->type == Resistor) |
| 28 | { | | |
| 29 | r->port_resistance_left = tWDF_getPortResistance(rL); | | |
| 30 | r->port_resistance_right = tWDF_getPortResistance(rR); | | |
| 31 | r->port_resistance_up = r->port_resistance_left + r->port_resistance_right; | | |
| 32 | r->port_conductance_up = 1.0f / r->port_resistance_up; | | |
| 33 | r->port_conductance_left = 1.0f / r->port_resistance_left; | | |
| 34 | r->port_conductance_right = 1.0f / r->port_resistance_right; | | |
| 35 | r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left); | | |
| 36 | | | |
| 37 | r->get_port_resistance = &get_port_resistance_for_series; | | |
| 38 | r->get_reflected_wave = &get_reflected_wave_for_series; | | |
| 39 | r->set_incident_wave = &set_incident_wave_for_series; | | |
| 40 | } | | |
| 41 | else if (r->type == ParallelAdaptor) | | |
| 42 | { | | |
| 43 | r->port_resistance_left = tWDF_getPortResistance(rL); | | |
| 44 | r->port_resistance_right = tWDF_getPortResistance(rR); | | |
| 45 | r->port_resistance_up = (r->port_resistance_left * r->port_resistance_right) / (r->port_resistance_left + r->port_resistance_right); | | |
| 46 | r->port_conductance_up = 1.0f / r->port_resistance_up; | | |
| 47 | r->port_conductance_left = 1.0f / r->port_resistance_left; | | |
| 48 | r->port_conductance_right = 1.0f / r->port_resistance_right; | | |
| 49 | r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left); | | |
| 50 | | | |
| 51 | r->get_port_resistance = &get_port_resistance_for_parallel; | | |
| 52 | r->get_reflected_wave = &get_reflected_wave_for_parallel; | | |
| 53 | r->set_incident_wave = &set_incident_wave_for_parallel; | | |
| 54 | } | | |
| 55 | else if (r->type == Resistor) | | |
| 56 | { | 27 | { |
| 57 | r->port_resistance_up = r->value; | 28 | r->port_resistance_up = r->value; |
| 58 | r->port_conductance_up = 1.0f / r->value; | 29 | r->port_conductance_up = 1.0f / r->value; |
| @@ -63,20 +34,71 @@ void tWDF_init(tWDF* const r, WDFComponentType type, float value, tWDF* const rL · 4 unmodified lines |
| 63 | } | 34 | } |
| 64 | else if (r->type == Capacitor) | 35 | else if (r->type == Capacitor) |
| 65 | { | 36 | { |
| 66 | r->port_resistance_up = 1.0f / (r->sample_rate * 2.0f * r->value); //based on trapezoidal discretization | 37 | r->port_conductance_up = r->sample_rate * 2.0f * r->value; |
| 67 | r->port_conductance_up = (1.0f / r->port_resistance_up); | 38 | r->port_resistance_up = 1.0f / r->port_conductance_up; //based on trapezoidal discretization |
| 68 | | 39 | |
| 69 | r->get_port_resistance = &get_port_resistance_for_capacitor; | 40 | r->get_port_resistance = &get_port_resistance_for_capacitor; |
| 70 | r->get_reflected_wave = &get_reflected_wave_for_capacitor; | 41 | r->get_reflected_wave = &get_reflected_wave_for_capacitor; |
| 71 | r->set_incident_wave = &set_incident_wave_for_leaf; | 42 | r->set_incident_wave = &set_incident_wave_for_leaf; |
| 72 | } | 43 | } |
| | 44 | else if (r->type == Inductor) |
| | 45 | { |
| | 46 | r->port_resistance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization |
| | 47 | r->port_conductance_up = 1.0f / r->port_resistance_up; |
| | 48 | |
| | 49 | r->get_port_resistance = &get_port_resistance_for_inductor; |
| | 50 | r->get_reflected_wave = &get_reflected_wave_for_capacitor; // same as capacitor |
| | 51 | r->set_incident_wave = &set_incident_wave_for_leaf_inverted; |
| | 52 | } |
| 73 | else if (r->type == ResistiveSource) | 53 | else if (r->type == ResistiveSource) |
| 74 | { | 54 | { |
| 75 | | 55 | r->port_resistance_up = 1.0f; // always use 1.0f for resistance |
| | 56 | r->port_conductance_up = 1.0f / 1.0f; |
| | 57 | // value is source voltage |
| | 58 | r->get_port_resistance = &get_port_resistance_for_resistive; |
| | 59 | r->get_reflected_wave = &get_reflected_wave_for_resistive; |
| | 60 | r->set_incident_wave = &set_incident_wave_for_leaf; |
| 76 | } | 61 | } |
| 77 | } | 62 | else if (r->type == Inverter) |
| 78 | | 63 | { |
| 79 | float tWDF_tick(tWDF* const r, float sample, uint8_t paramsChanged) | 64 | r->port_resistance_up = tWDF_getPortResistance(r->child_left); |
| | 65 | r->port_conductance_up = 1.0f / r->port_resistance_up; |
| | 66 | |
| | 67 | r->get_port_resistance = &get_port_resistance_for_inverter; |
| | 68 | r->get_reflected_wave = &get_reflected_wave_for_inverter; |
| | 69 | r->set_incident_wave = &set_incident_wave_for_inverter; |
| | 70 | } |
| | 71 | else if (r->type == SeriesAdaptor) |
| | 72 | { |
| | 73 | r->port_resistance_left = tWDF_getPortResistance(r->child_left); |
| | 74 | r->port_resistance_right = tWDF_getPortResistance(r->child_right); |
| | 75 | r->port_resistance_up = r->port_resistance_left + r->port_resistance_right; |
| | 76 | r->port_conductance_up = 1.0f / r->port_resistance_up; |
| | 77 | r->port_conductance_left = 1.0f / r->port_resistance_left; |
| | 78 | r->port_conductance_right = 1.0f / r->port_resistance_right; |
| | 79 | r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left); |
| | 80 | |
| | 81 | r->get_port_resistance = &get_port_resistance_for_series; |
| | 82 | r->get_reflected_wave = &get_reflected_wave_for_series; |
| | 83 | r->set_incident_wave = &set_incident_wave_for_series; |
| | 84 | } |
| | 85 | else if (r->type == ParallelAdaptor) |
| | 86 | { |
| | 87 | r->port_resistance_left = tWDF_getPortResistance(r->child_left); |
| | 88 | r->port_resistance_right = tWDF_getPortResistance(r->child_right); |
| | 89 | r->port_resistance_up = (r->port_resistance_left * r->port_resistance_right) / (r->port_resistance_left + r->port_resistance_right); |
| | 90 | r->port_conductance_up = 1.0f / r->port_resistance_up; |
| | 91 | r->port_conductance_left = 1.0f / r->port_resistance_left; |
| | 92 | r->port_conductance_right = 1.0f / r->port_resistance_right; |
| | 93 | r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left); |
| | 94 | |
| | 95 | r->get_port_resistance = &get_port_resistance_for_parallel; |
| | 96 | r->get_reflected_wave = &get_reflected_wave_for_parallel; |
| | 97 | r->set_incident_wave = &set_incident_wave_for_parallel; |
| | 98 | } |
| | 99 | } |
| | 100 | |
| | 101 | float tWDF_tick(tWDF* const r, tWDFNonlinear* const n, float sample, uint8_t paramsChanged) |
| 80 | { | 102 | { |
| 81 | //step 0 : update port resistances if something changed | 103 | //step 0 : update port resistances if something changed |
| 82 | if (paramsChanged) tWDF_getPortResistance(r); | 104 | if (paramsChanged) tWDF_getPortResistance(r); |
| @@ -88,13 +110,13 @@ float tWDF_tick(tWDF* const r, float sample, uint8_t paramsChanged) · 5 unmodified lines |
| 88 | float incident_wave = tWDF_getReflectedWave(r); | 110 | float incident_wave = tWDF_getReflectedWave(r); |
| 89 | | 111 | |
| 90 | //step 3 : do root scattering computation | 112 | //step 3 : do root scattering computation |
| 91 | float reflected_wave = (2.0f * input) - incident_wave; | 113 | float reflected_wave = tWDFNonlinear_calculateReflectedWave(n, input, incident_wave); |
| 92 | | 114 | |
| 93 | //step 4 : propigate waves down the tree | 115 | //step 4 : propogate waves down the tree |
| 94 | tWDF_setIncidentWave(r, reflected_wave); | 116 | tWDF_setIncidentWave(r, reflected_wave); |
| 95 | | 117 | |
| 96 | //step 5 : grab whatever voltages or currents we want as outputs | 118 | //step 5 : grab whatever voltages or currents we want as outputs |
| 97 | return -1.0f * tWDF_getVoltage(r->outpoint); | 119 | return reflected_wave*0.5f + incident_wave*0.5f;//tWDF_getVoltage(r->outpoint); |
| 98 | } | 120 | } |
| 99 | | 121 | |
| 100 | void tWDF_setValue(tWDF* const r, float value) | 122 | void tWDF_setValue(tWDF* const r, float value) |
| @@ -149,7 +171,10 @@ float tWDF_getCurrent(tWDF* const r) · 48 unmodified lines |
| 149 | return (((r->incident_wave_up * 0.5f) - (r->reflected_wave_up * 0.5f)) * r->port_conductance_up); | 171 | return (((r->incident_wave_up * 0.5f) - (r->reflected_wave_up * 0.5f)) * r->port_conductance_up); |
| 150 | } | 172 | } |
| 151 | | 173 | |
| 152 | // static functions to be pointed to | 174 | //============ Static Functions to be Pointed To ==================== |
| | 175 | //=================================================================== |
| | 176 | //============ Get and Calculate Port Resistances =================== |
| | 177 | |
| 153 | static float get_port_resistance_for_resistor(tWDF* const r) | 178 | static float get_port_resistance_for_resistor(tWDF* const r) |
| 154 | { | 179 | { |
| 155 | r->port_resistance_up = r->value; | 180 | r->port_resistance_up = r->value; |
| @@ -160,12 +185,33 @@ static float get_port_resistance_for_resistor(tWDF* const r) · 4 unmodified lines |
| 160 | | 185 | |
| 161 | static float get_port_resistance_for_capacitor(tWDF* const r) | 186 | static float get_port_resistance_for_capacitor(tWDF* const r) |
| 162 | { | 187 | { |
| 163 | r->port_resistance_up = 1.0f / (r->sample_rate * 2.0f * r->value); //based on trapezoidal discretization | 188 | r->port_conductance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization |
| 164 | r->port_conductance_up = (1.0f / r->port_resistance_up); | 189 | r->port_resistance_up = (1.0f / r->port_conductance_up); |
| 165 | | 190 | |
| 166 | return r->port_resistance_up; | 191 | return r->port_resistance_up; |
| 167 | } | 192 | } |
| 168 | | 193 | |
| | 194 | static float get_port_resistance_for_inductor(tWDF* const r) |
| | 195 | { |
| | 196 | r->port_resistance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization |
| | 197 | r->port_conductance_up = (1.0f / r->port_resistance_up); |
| | 198 | |
| | 199 | return r->port_resistance_up; |
| | 200 | } |
| | 201 | |
| | 202 | static float get_port_resistance_for_resistive(tWDF* const r) |
| | 203 | { |
| | 204 | return r->port_resistance_up; |
| | 205 | } |
| | 206 | |
| | 207 | static float get_port_resistance_for_inverter(tWDF* const r) |
| | 208 | { |
| | 209 | r->port_resistance_up = tWDF_getPortResistance(r->child_left); |
| | 210 | r->port_conductance_up = 1.0f / r->port_resistance_up; |
| | 211 | |
| | 212 | return r->port_resistance_up; |
| | 213 | } |
| | 214 | |
| 169 | static float get_port_resistance_for_series(tWDF* const r) | 215 | static float get_port_resistance_for_series(tWDF* const r) |
| 170 | { | 216 | { |
| 171 | r->port_resistance_left = tWDF_getPortResistance(r->child_left); | 217 | r->port_resistance_left = tWDF_getPortResistance(r->child_left); |
| @@ -192,11 +238,24 @@ static float get_port_resistance_for_parallel(tWDF* const r) · 20 unmodified lines |
| 192 | return r->port_resistance_up; | 238 | return r->port_resistance_up; |
| 193 | } | 239 | } |
| 194 | | 240 | |
| | 241 | //=================================================================== |
| | 242 | //================ Set Incident Waves =============================== |
| | 243 | |
| 195 | static void set_incident_wave_for_leaf(tWDF* const r, float incident_wave) | 244 | static void set_incident_wave_for_leaf(tWDF* const r, float incident_wave) |
| 196 | { | 245 | { |
| 197 | r->incident_wave_up = incident_wave; | 246 | r->incident_wave_up = incident_wave; |
| 198 | } | 247 | } |
| 199 | | 248 | |
| | 249 | static void set_incident_wave_for_leaf_inverted(tWDF* const r, float incident_wave) |
| | 250 | { |
| | 251 | r->incident_wave_up = -1.0f * incident_wave; |
| | 252 | } |
| | 253 | |
| | 254 | static void set_incident_wave_for_inverter(tWDF* const r, float incident_wave) |
| | 255 | { |
| | 256 | tWDF_setIncidentWave(r->child_left, -1.0f * incident_wave); |
| | 257 | } |
| | 258 | |
| 200 | static void set_incident_wave_for_series(tWDF* const r, float incident_wave) | 259 | static void set_incident_wave_for_series(tWDF* const r, float incident_wave) |
| 201 | { | 260 | { |
| 202 | float gamma_left = r->port_resistance_left * r->gamma_zero; | 261 | float gamma_left = r->port_resistance_left * r->gamma_zero; |
| @@ -225,6 +284,9 @@ static void set_incident_wave_for_parallel(tWDF* const r, float incident_wave) · 22 unmodified lines |
| 225 | tWDF_setIncidentWave(r->child_right, gamma_left * left_wave + (gamma_right - 1.0f) * right_wave + incident_wave); | 284 | tWDF_setIncidentWave(r->child_right, gamma_left * left_wave + (gamma_right - 1.0f) * right_wave + incident_wave); |
| 226 | } | 285 | } |
| 227 | | 286 | |
| | 287 | //=================================================================== |
| | 288 | //================ Get Reflected Waves ============================== |
| | 289 | |
| 228 | static float get_reflected_wave_for_resistor(tWDF* const r) | 290 | static float get_reflected_wave_for_resistor(tWDF* const r) |
| 229 | { | 291 | { |
| 230 | r->reflected_wave_up = 0.0f; | 292 | r->reflected_wave_up = 0.0f; |
| @@ -237,6 +299,18 @@ static float get_reflected_wave_for_capacitor(tWDF* const r) · 6 unmodified lines |
| 237 | return r->reflected_wave_up; | 299 | return r->reflected_wave_up; |
| 238 | } | 300 | } |
| 239 | | 301 | |
| | 302 | static float get_reflected_wave_for_resistive(tWDF* const r) |
| | 303 | { |
| | 304 | r->reflected_wave_up = r->value; |
| | 305 | return r->reflected_wave_up; |
| | 306 | } |
| | 307 | |
| | 308 | static float get_reflected_wave_for_inverter(tWDF* const r) |
| | 309 | { |
| | 310 | r->reflected_wave_up = -1.0f * tWDF_getReflectedWave(r->child_left); |
| | 311 | return r->reflected_wave_up; |
| | 312 | } |
| | 313 | |
| 240 | static float get_reflected_wave_for_series(tWDF* const r) | 314 | static float get_reflected_wave_for_series(tWDF* const r) |
| 241 | { | 315 | { |
| 242 | //-( downPorts[0]->a + downPorts[1]->a ); | 316 | //-( downPorts[0]->a + downPorts[1]->a ); |
| @@ -251,6 +325,87 @@ static float get_reflected_wave_for_parallel(tWDF* const r) · 8 unmodified lines |
| 251 | return (gamma_left * tWDF_getReflectedWave(r->child_left) + gamma_right * tWDF_getReflectedWave(r->child_right)); | 325 | return (gamma_left * tWDF_getReflectedWave(r->child_left) + gamma_right * tWDF_getReflectedWave(r->child_right)); |
| 252 | } | 326 | } |
| 253 | | 327 | |
| | 328 | // WDF Nonlinear |
| | 329 | void tWDFNonlinear_init(tWDFNonlinear* const n, WDFRootType type, tWDF* const child) |
| | 330 | { |
| | 331 | n->type = type; |
| | 332 | n->child = child; |
| | 333 | if (n->type == IdealSource) |
| | 334 | { |
| | 335 | n->calculate_reflected_wave = &calculate_reflected_wave_for_ideal; |
| | 336 | } |
| | 337 | else if (n->type == Diode) |
| | 338 | { |
| | 339 | n->calculate_reflected_wave = &calculate_reflected_wave_for_diode; |
| | 340 | } |
| | 341 | else if (n->type == DiodePair) |
| | 342 | { |
| | 343 | //n->calculate_reflected_wave = &calculate_reflected_wave_for_ideal; |
| | 344 | } |
| | 345 | } |
| | 346 | |
| | 347 | float tWDFNonlinear_calculateReflectedWave(tWDFNonlinear* const n, float input, float incident_wave) |
| | 348 | { |
| | 349 | return n->calculate_reflected_wave(n, input, incident_wave); |
| | 350 | } |
| | 351 | |
| | 352 | static float calculate_reflected_wave_for_ideal(tWDFNonlinear* const n, float input, float incident_wave) |
| | 353 | { |
| | 354 | return (2.0f * input) - incident_wave; |
| | 355 | } |
| | 356 | |
| | 357 | static const float l2A = 0.1640425613334452f; |
| | 358 | static const float l2B = -1.098865286222744f; |
| | 359 | static const float l2Y = 3.148297929334117f; |
| | 360 | static const float l2K = -2.213475204444817f; |
| | 361 | static float log2Approximation(float x) |
| | 362 | { |
| | 363 | return (l2A * x*x*x) + (l2B * x*x) + (l2Y * x) + l2K; |
| | 364 | } |
| | 365 | |
| | 366 | static const float wX1 = -3.684303659906469f; |
| | 367 | static const float wX2 = 1.972967391708859f; |
| | 368 | static const float wA = 0.009451797158780131f; |
| | 369 | static const float wB = 0.1126446405111627f; |
| | 370 | static const float wY = 0.4451353886588814f; |
| | 371 | static const float wK = 0.5836596684310648f; |
| | 372 | |
| | 373 | static float wrightOmega3(float x) |
| | 374 | { |
| | 375 | if (x <= wX1) |
| | 376 | { |
| | 377 | return 0; |
| | 378 | } |
| | 379 | else if (x < wX2) |
| | 380 | { |
| | 381 | return (wA * x*x*x) + (wB * x*x) + (wY * x) + wK; |
| | 382 | } |
| | 383 | else |
| | 384 | { |
| | 385 | return x - logf(x); |
| | 386 | } |
| | 387 | } |
| | 388 | |
| | 389 | static float wrightOmegaApproximation(float x) |
| | 390 | { |
| | 391 | float w3 = wrightOmega3(x); |
| | 392 | return w3 - ((w3 - expf(x - w3)) / (w3 + 1.0f)); |
| | 393 | } |
| | 394 | |
| | 395 | static float lambertW(float a, float r, float I, float iVT) |
| | 396 | { |
| | 397 | return wrightOmegaApproximation(((a + r*I) * iVT) + log((r * I) * iVT)); |
| | 398 | } |
| | 399 | |
| | 400 | #define Is_DIODE 2.52e-9 |
| | 401 | #define VT_DIODE 0.02585 |
| | 402 | static float calculate_reflected_wave_for_diode(tWDFNonlinear* const n, float input, float incident_wave) |
| | 403 | { |
| | 404 | float a = incident_wave; |
| | 405 | float r = n->child->port_resistance_up; |
| | 406 | return a + 2.0f*r*Is_DIODE - 2.0f*VT_DIODE*lambertW(a, r, Is_DIODE, 1.0f/VT_DIODE); |
| | 407 | } |
| | 408 | |
| 254 | | 409 | |
| 255 | | 410 | |
| 256 | | 411 | |