Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

wdf.cpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. //wdf.cpp
  2. #include <stdio.h>
  3. #include <inttypes.h>
  4. #include <cmath>
  5. #include "wdf.h"
  6. using std::abs;
  7. WDF::WDF() {}
  8. void WDF::setWD(T val) {
  9. WD = val;
  10. state = val;
  11. DUMP(printf("DOWN\tWDF\t%c\tWD=%f\tWU=%f\tV=%f\n",type,WD,WU,(WD+WU)/2.0));
  12. }
  13. void OnePort::setWD(T val) {
  14. WD = val;
  15. state = val;
  16. DUMP(printf("DOWN\tOneport\t%c\tWD=%f\tWU=%f\tV=%f\n",type,WD,WU,(WD+WU)/2.0));
  17. }
  18. T WDF::Voltage() {
  19. T Volts = (WU + WD) / 2.0;
  20. return Volts;
  21. }
  22. T WDF::Current() {
  23. T Amps = (WU - WD) / (2.0*PortRes);
  24. return Amps;
  25. }
  26. template <class Port1, class Port2>ser::ser(Port1 *l, Port2 *r) : Adaptor(THREEPORT) {
  27. left = l;
  28. right = r;
  29. PortRes = l->PortRes + r->PortRes;
  30. type = 'S';
  31. }
  32. ser::ser(R* l, par* r) : Adaptor(THREEPORT) {
  33. left = l;
  34. right = r;
  35. PortRes = l->PortRes + r->PortRes;
  36. type = 'S';
  37. }
  38. ser::ser(C* l, R* r) : Adaptor(THREEPORT) {
  39. left = l;
  40. right = r;
  41. PortRes = l->PortRes + r->PortRes;
  42. type = 'S';
  43. }
  44. ser::ser(C* l, V* r) : Adaptor(THREEPORT) {
  45. left = l;
  46. right = r;
  47. PortRes = l->PortRes + r->PortRes;
  48. type = 'S';
  49. }
  50. template <class Port>inv::inv(Port *l) : Adaptor(PASSTHROUGH) {
  51. left = l;
  52. PortRes = l->PortRes;
  53. type = 'I';
  54. }
  55. inv::inv(ser *l) : Adaptor(PASSTHROUGH) {
  56. left = l;
  57. PortRes = l->PortRes;
  58. type = 'I';
  59. }
  60. T ser::waveUp() {
  61. //Adaptor::WU = -left->waveUp() - right->waveUp();
  62. WDF::WU = -left->waveUp() - right->waveUp();
  63. DUMP(printf("UP\tser\tWU=%f\tWD=%f\tV=%f\n",WU,WD,(WD+WU)/2.0));
  64. return WU;
  65. }
  66. template <class Port1, class Port2>par::par(Port1 *l, Port2 *r) : Adaptor(THREEPORT) {
  67. left = l;
  68. right = r;
  69. PortRes = 1.0 / (1.0 / l->PortRes + 1.0 / r->PortRes);
  70. type = 'P';
  71. }
  72. par::par(inv* l, R* r) : Adaptor(THREEPORT) {
  73. left = l;
  74. right = r;
  75. PortRes = 1.0 / (1.0 / l->PortRes + 1.0 / r->PortRes);
  76. type = 'P';
  77. }
  78. par::par(inv* l, V* r) : Adaptor(THREEPORT) {
  79. left = l;
  80. right = r;
  81. PortRes = 1.0 / (1.0 / l->PortRes + 1.0 / r->PortRes);
  82. type = 'P';
  83. }
  84. par::par(C* l, R* r) : Adaptor(THREEPORT) {
  85. left = l;
  86. right = r;
  87. PortRes = 1.0 / (1.0 / l->PortRes + 1.0 / r->PortRes);
  88. type = 'P';
  89. }
  90. T par::waveUp() {
  91. T G23 = 1.0 / left->PortRes + 1.0 / right->PortRes;
  92. WDF::WU = (1.0 / left->PortRes)/G23*left->waveUp() + (1.0 / right->PortRes)/G23*right->waveUp();
  93. DUMP(printf("UP\tpar\tWU=%f\tWD=%f\tV=%f\n",WU,WD,(WD+WU)/2.0));
  94. return WU;
  95. }
  96. Adaptor::Adaptor(int flag) {
  97. WU = 0.0;
  98. WD = 0.0;
  99. switch (flag) {
  100. case ONEPORT:
  101. left = NULL;
  102. right = NULL;
  103. break;
  104. case PASSTHROUGH:
  105. right = NULL;
  106. break;
  107. default:
  108. case THREEPORT:
  109. break;
  110. }
  111. }
  112. void ser::setWD(T waveparent) {
  113. Adaptor::setWD(waveparent);
  114. DUMP(printf("SER WP=%f\n",waveparent));
  115. left->setWD(left->WU-(2.0*left->PortRes/(PortRes+left->PortRes+right->PortRes))*(waveparent+left->WU+right->WU));
  116. right->setWD(right->WU-(2.0*right->PortRes/(PortRes+left->PortRes+right->PortRes))*(waveparent+left->WU+right->WU));
  117. }
  118. void par::setWD(T waveparent) {
  119. Adaptor::setWD(waveparent);
  120. DUMP(printf("PAR WP=%f\n",waveparent));
  121. T p = 2.0*(waveparent/PortRes + left->WU/left->PortRes + right->WU/right->PortRes)/(1.0/PortRes + 1.0/left->PortRes + 1.0/right->PortRes);
  122. left->setWD((p - left->WU));
  123. right->setWD((p - right->WU));
  124. }
  125. T inv::waveUp() {
  126. ///////////WD = -left->WD;
  127. WU = -left->waveUp(); //-
  128. DUMP(printf("UP\tinv\tWU=%f\tWD=%f\tV=%f\n",WU,WD,(WD+WU)/2.0));
  129. return WU;
  130. }
  131. void inv::setWD(T waveparent) {
  132. WDF::setWD(waveparent);
  133. DUMP(printf("INV WP=%f\n",waveparent));
  134. //left->WD = -waveparent; //-
  135. ///////////left->WU = -WU;
  136. left->setWD(-waveparent); //-
  137. }
  138. R::R(T res) : Adaptor(ONEPORT) {
  139. PortRes = res;
  140. type = 'R';
  141. }
  142. T R::waveUp() {
  143. WU = 0.0;
  144. DUMP(printf("UP\tR\tWU=%f\tWD=%f\tV=%f\n",WU, WD,(WD+WU)/2.0));
  145. return WU;
  146. }
  147. C::C(T c, T fs) : Adaptor(ONEPORT) {
  148. PortRes = 1.0/(2.0*c*fs);
  149. state = 0.0;
  150. type = 'C';
  151. }
  152. T C::waveUp() {
  153. WU = state;
  154. DUMP(printf("UP\tC\tWU=%f\tWD=%f\tV=%f\n",WU,WD,(WD+WU)/2.0));
  155. return WU;
  156. }
  157. V::V(T ee, T r) : Adaptor(ONEPORT) {
  158. e = ee;
  159. PortRes = r;
  160. WD = 0.0; //always?
  161. type = 'V';
  162. }
  163. T V::waveUp() {
  164. T watts = 100.0;
  165. WU = 2.0*e - WD;
  166. if (Voltage()*Current() > watts) WU *= 0.999;//0.9955;
  167. DUMP(printf("UP\tV\tWU=%f\tWD=%f\tV=%f\n",WU, WD,(WD+WU)/2.0));
  168. return WU;
  169. }
  170. inline T _exp(const T x)
  171. {
  172. if(x < 10.0 && x > 10.0)
  173. return 1.0 + x + x*x/2.0 + x*x*x/6.0 + x*x*x*x/24.0 + x*x*x*x*x/120.0
  174. + x*x*x*x*x*x/720.0 + x*x*x*x*x*x*x/5040.0;
  175. else
  176. return exp(x);
  177. }
  178. inline T _log(const T x)
  179. {
  180. if(x > 10)
  181. return log(x);
  182. const T a=(x-1)/(x+1);
  183. return 2.0*(a+a*a*a/3.0+a*a*a*a*a/5.0+a*a*a*a*a*a*a/7.0+a*a*a*a*a*a*a*a*a/9.0);
  184. }
  185. inline T _pow(const T a, const T b)
  186. {
  187. return pow(a,b);
  188. }
  189. T Triode::ffg(T VG) {
  190. return (G.WD-G.PortRes*(gg*_pow(_log(1.0+_exp(cg*VG))/cg,e)+ig0)-VG);
  191. }
  192. T Triode::fgdash(T VG) {
  193. T a1 = exp(cg*VG);
  194. T b1 = -e*pow(log(a1+1.0)/cg,e-1.0);
  195. T c1 = a1/(a1+1.0)*gg*G.PortRes;
  196. return (b1*c1);
  197. }
  198. T Triode::ffp(T VP) {
  199. static bool prepared = false;
  200. static double scale;
  201. static double coeff[4];
  202. if(!prepared) {
  203. //go go series expansion
  204. const double L2 = log(2.0);
  205. const double scale = pow(L2,gamma-2)/(8.0*pow(c,gamma));
  206. coeff[0] = 8.0*L2*L2*scale;
  207. coeff[1] = gamma*c*L2*4*scale;
  208. coeff[2] = (c*c*gamma*gamma+L2*c*c*gamma-c*c*gamma)*scale;
  209. coeff[3] = 0.0;
  210. prepared = true;
  211. }
  212. double A = VP/mu+vg;
  213. return (P.WD+P.PortRes*((g*(coeff[0]+coeff[1]*A+coeff[2]*A*A))+(G.WD-vg)/G.PortRes)-VP);
  214. printf("%f\n", VP/mu+vg);
  215. return (P.WD+P.PortRes*((g*_pow(_log(1.0+_exp(c*(VP/mu+vg)))/c,gamma))+(G.WD-vg)/G.PortRes)-VP);
  216. } // ^
  217. T Triode::fpdash(T VP) {
  218. T a1 = exp(c*(vg+VP/mu));
  219. T b1 = a1/(mu*(a1+1.0));
  220. T c1 = g*gamma*P.PortRes*pow(log(a1+1.0)/c,gamma-1.0);
  221. return (c1*b1);
  222. }
  223. T Triode::ffk() {
  224. return (K.WD - K.PortRes*(g*pow(log(1.0+exp(c*(vp/mu+vg)))/c,gamma)));
  225. }
  226. /*
  227. T Triode::secantfg(T *i1, T *i2) {
  228. T vgn = 0.0;
  229. T init = *i1;
  230. for (int i = 0; i<ITER; ++i) {
  231. vgn = *i1 - fg(*i1)*(*i1-*i2)/(fg(*i1)-fg(*i2));
  232. *i2 = *i1;
  233. *i1 = vgn;
  234. if ((fabs(fg(vgn))) < EPSILON) break;
  235. }
  236. if ((fabs(fg(vgn)) >= EPSILON)) {
  237. DUMP(fprintf(stderr,"Vg did not converge\n"));
  238. return init;
  239. }
  240. return vgn;
  241. }
  242. T Triode::newtonfg(T *i1) {
  243. T init = *i1;
  244. if (fabs(fg(*i1)) < EPSILON || fgdash(*i1)==0.0) return *i1;
  245. T vgn = 0.0;
  246. for (int i = 0; i<ITER; ++i) {
  247. vgn = *i1 - fg(*i1)/fgdash(*i1);
  248. *i1 = vgn;
  249. if (fabs(fg(vgn)) < EPSILON) break;
  250. }
  251. if ((fabs(fg(vgn)) >= EPSILON)) {
  252. // vgn = init;
  253. DUMP(fprintf(stderr,"Vg did not converge\n"));
  254. }
  255. return vgn;
  256. }
  257. T Triode::newtonfp(T *i1) {
  258. T init = *i1;
  259. if (fabs(fp(*i1)) < EPSILON || fpdash(*i1)==0.0) return *i1;
  260. T vpn = 0.0;
  261. for (int i = 0; i<ITER; ++i) {
  262. vpn = *i1 - fp(*i1)/fpdash(*i1);
  263. *i1 = vpn;
  264. if (fabs(fp(vpn)) < EPSILON) break;
  265. }
  266. if ((fabs(fp(vpn)) >= EPSILON)) {
  267. // vpn = init;
  268. DUMP(fprintf(stderr,"Vp did not converge\n"));
  269. }
  270. return vpn;
  271. }
  272. T Triode::secantfp(T *i1, T *i2) {
  273. T vpn = 0.0;
  274. for (int i = 0; i<ITER; ++i) {
  275. vpn = *i1 - fp(*i1)*(*i1-*i2)/(fp(*i1)-fp(*i2));
  276. *i2 = *i1;
  277. *i1 = vpn;
  278. if ((fabs(fp(vpn))) < EPSILON) break;
  279. }
  280. if ((fabs(fp(vpn)) >= EPSILON))
  281. DUMP(fprintf(stderr,"Vp did not converge\n"));
  282. return vpn;
  283. }
  284. */
  285. //****************************************************************************80
  286. // Purpose:
  287. //
  288. // Brent's method root finder.
  289. //
  290. // Licensing:
  291. //
  292. // This code below is distributed under the GNU LGPL license.
  293. //
  294. // Author:
  295. //
  296. // Original FORTRAN77 version by Richard Brent.
  297. // C++ version by John Burkardt.
  298. // Adapted for zamvalve by Damien Zammit.
  299. T Triode::r8_abs ( T x )
  300. {
  301. T value;
  302. if ( 0.0 <= x )
  303. {
  304. value = x;
  305. }
  306. else
  307. {
  308. value = - x;
  309. }
  310. return value;
  311. }
  312. Triode::Triode()
  313. {
  314. T r = 1.0;
  315. while ( 1.0 < ( T ) ( 1.0 + r ) )
  316. {
  317. r = r / 2.0;
  318. }
  319. r *= 2.0;
  320. r8_epsilon = r;
  321. }
  322. T Triode::r8_max ( T x, T y )
  323. {
  324. T value;
  325. if ( y < x )
  326. {
  327. value = x;
  328. }
  329. else
  330. {
  331. value = y;
  332. }
  333. return value;
  334. }
  335. T Triode::r8_sign ( T x )
  336. {
  337. T value;
  338. if ( x < 0.0 )
  339. {
  340. value = -1.0;
  341. }
  342. else
  343. {
  344. value = 1.0;
  345. }
  346. return value;
  347. }
  348. T Triode::zeroffp ( T a, T b, T t )
  349. {
  350. T c;
  351. T d;
  352. T e;
  353. T fa;
  354. T fb;
  355. T fc;
  356. T m;
  357. T macheps;
  358. T p;
  359. T q;
  360. T r;
  361. T s;
  362. T sa;
  363. T sb;
  364. T tol;
  365. //
  366. // Make local copies of A and B.
  367. //
  368. sa = a;
  369. sb = b;
  370. fa = ffp ( sa );
  371. fb = ffp ( sb );
  372. c = sa;
  373. fc = fa;
  374. e = sb - sa;
  375. d = e;
  376. macheps = r8_epsilon;
  377. for ( ; ; )
  378. {
  379. if ( abs ( fc ) < abs ( fb ) )
  380. {
  381. sa = sb;
  382. sb = c;
  383. c = sa;
  384. fa = fb;
  385. fb = fc;
  386. fc = fa;
  387. }
  388. tol = 2.0 * macheps * abs ( sb ) + t;
  389. m = 0.5 * ( c - sb );
  390. if ( abs ( m ) <= tol || fb == 0.0 )
  391. {
  392. break;
  393. }
  394. if ( abs ( e ) < tol || abs ( fa ) <= abs ( fb ) )
  395. {
  396. e = m;
  397. d = e;
  398. }
  399. else
  400. {
  401. s = fb / fa;
  402. if ( sa == c )
  403. {
  404. p = 2.0 * m * s;
  405. q = 1.0 - s;
  406. }
  407. else
  408. {
  409. q = fa / fc;
  410. r = fb / fc;
  411. p = s * ( 2.0 * m * q * ( q - r ) - ( sb - sa ) * ( r - 1.0 ) );
  412. q = ( q - 1.0 ) * ( r - 1.0 ) * ( s - 1.0 );
  413. }
  414. if ( 0.0 < p )
  415. {
  416. q = - q;
  417. }
  418. else
  419. {
  420. p = - p;
  421. }
  422. s = e;
  423. e = d;
  424. if ( 2.0 * p < 3.0 * m * q - abs ( tol * q ) &&
  425. p < abs ( 0.5 * s * q ) )
  426. {
  427. d = p / q;
  428. }
  429. else
  430. {
  431. e = m;
  432. d = e;
  433. }
  434. }
  435. sa = sb;
  436. fa = fb;
  437. if ( tol < abs ( d ) )
  438. {
  439. sb = sb + d;
  440. }
  441. else if ( 0.0 < m )
  442. {
  443. sb = sb + tol;
  444. }
  445. else
  446. {
  447. sb = sb - tol;
  448. }
  449. fb = ffp ( sb );
  450. if ( ( 0.0 < fb && 0.0 < fc ) || ( fb <= 0.0 && fc <= 0.0 ) )
  451. {
  452. c = sa;
  453. fc = fa;
  454. e = sb - sa;
  455. d = e;
  456. }
  457. }
  458. return sb;
  459. }
  460. T Triode::zeroffg ( T a, T b, T t )
  461. {
  462. T c;
  463. T d;
  464. T e;
  465. T fa;
  466. T fb;
  467. T fc;
  468. T m;
  469. T macheps;
  470. T p;
  471. T q;
  472. T r;
  473. T s;
  474. T sa;
  475. T sb;
  476. T tol;
  477. //
  478. // Make local copies of A and B.
  479. //
  480. sa = a;
  481. sb = b;
  482. fa = ffg ( sa );
  483. fb = ffg ( sb );
  484. c = sa;
  485. fc = fa;
  486. e = sb - sa;
  487. d = e;
  488. macheps = r8_epsilon;
  489. for ( ; ; )
  490. {
  491. if ( abs ( fc ) < abs ( fb ) )
  492. {
  493. sa = sb;
  494. sb = c;
  495. c = sa;
  496. fa = fb;
  497. fb = fc;
  498. fc = fa;
  499. }
  500. tol = 2.0 * macheps * abs ( sb ) + t;
  501. m = 0.5 * ( c - sb );
  502. if ( abs ( m ) <= tol || fb == 0.0 )
  503. {
  504. break;
  505. }
  506. if ( abs ( e ) < tol || abs ( fa ) <= abs ( fb ) )
  507. {
  508. e = m;
  509. d = e;
  510. }
  511. else
  512. {
  513. s = fb / fa;
  514. if ( sa == c )
  515. {
  516. p = 2.0 * m * s;
  517. q = 1.0 - s;
  518. }
  519. else
  520. {
  521. q = fa / fc;
  522. r = fb / fc;
  523. p = s * ( 2.0 * m * q * ( q - r ) - ( sb - sa ) * ( r - 1.0 ) );
  524. q = ( q - 1.0 ) * ( r - 1.0 ) * ( s - 1.0 );
  525. }
  526. if ( 0.0 < p )
  527. {
  528. q = - q;
  529. }
  530. else
  531. {
  532. p = - p;
  533. }
  534. s = e;
  535. e = d;
  536. if ( 2.0 * p < 3.0 * m * q - abs ( tol * q ) &&
  537. p < abs ( 0.5 * s * q ) )
  538. {
  539. d = p / q;
  540. }
  541. else
  542. {
  543. e = m;
  544. d = e;
  545. }
  546. }
  547. sa = sb;
  548. fa = fb;
  549. if ( tol < abs ( d ) )
  550. {
  551. sb = sb + d;
  552. }
  553. else if ( 0.0 < m )
  554. {
  555. sb = sb + tol;
  556. }
  557. else
  558. {
  559. sb = sb - tol;
  560. }
  561. fb = ffg ( sb );
  562. if ( ( 0.0 < fb && 0.0 < fc ) || ( fb <= 0.0 && fc <= 0.0 ) )
  563. {
  564. c = sa;
  565. fc = fa;
  566. e = sb - sa;
  567. d = e;
  568. }
  569. }
  570. return sb;
  571. }