1from __future__ import division 2import os, quik 3 4 5class MyLoader(object): 6 7 def load_text(self, fname): 8 if fname.startswith("%"): 9 # hack for directly including guitarix gx_plugin.h 10 guitarix_headers = "../../../src/headers" 11 with open(os.path.join(guitarix_headers, fname[1:])) as f: 12 return "".join([line for line in f if not (line.startswith("#include") or line.startswith("#pragma once"))]) 13 else: 14 with open(fname) as f: 15 return f.read() 16 17 def load_template(self, name): 18 return globals()[name] 19 20 21class Template(quik.Template): 22 def render(self, namespace, loader=MyLoader()): 23 return quik.Template.render(self, namespace, loader) 24 25c_template_top = Template("""\ 26%if (@build_script)\ 27// generated by @build_script 28%else\ 29// generated automatically 30%end 31// DO NOT MODIFY! 32#include <iostream> 33#include <cmath> 34#include <list> 35%% %if (@method == "hybr" || @method == "lm") 36%if (@method == "lm") 37#include <cminpack.h> 38%else 39#include <float.h> 40%end 41#include <Eigen/Core> 42%if (@np > 0) 43#include <Eigen/LU> 44%end 45%if (@dev_interface)%% just for convenience, to make stand alone sources 46%include ("%gx_compiler.h") 47%include ("%gx_plugin.h") 48%else 49#include "gx_compiler.h" 50#include "gx_plugin.h" 51%end 52 53using namespace Eigen; 54 55#define N_(x) (x) 56 57#define creal @c_real 58 59static inline int sign(creal v) { 60 return v < 0 ? -1 : 1; 61} 62 63static inline int Heaviside(creal v) { 64 return v < 0 ? 0 : 1; // Heaviside(0) == 1/2 in sympy but shouldn't matter 65} 66 67static Matrix<creal, @nx, 1> g_x; 68creal g_v_data[@nn]; 69static Map<Matrix<creal, @nn, 1> >g_v(g_v_data); 70static int g_info; 71static int g_nfev; 72 73%if (@dev_interface) 74static creal g_fnorm; 75static Array<creal, @nni, 1> g_min; 76static Array<creal, @nni, 1> g_max; 77 78#define INTERFACE_VERSION 5 79 80extern "C" __attribute__ ((visibility ("default"))) 81int get_interface_version() { 82 return INTERFACE_VERSION; 83} 84 85extern "C" __attribute__ ((visibility ("default"))) 86void get_structure(const char **name, int *data_size, int *samplerate, const int **shapes, const int (**comp_sz)[6], 87 const char ***pins, const char ***comp_names, const char **method, const char ***pot_vars, 88 const double **pot, const char ***out_labels, const char **comment) { 89 static const char *n = "@name"; 90 static int sz[] = { @nx, @ni, @no, @npl, @nn, @nni, @nno, @nc, -1 }; // nx, ni, no, npl, nn, nni, nno, nc, -1 91 static int nn_sz[][6] = { // component v_slice, p_slice, i_slice 92 %for @c in @components:\ 93 {@c.v_slice.start, @c.v_slice.stop, @c.p_slice.start, @c.p_slice.stop, @c.i_slice.start, @c.i_slice.stop}, 94 %end 95 }; 96 static const char *nn_name[] = { // component names 97 %for @c in @components:\ 98 "@c.name", "@c.namespace", 99 %end 0 100 }; 101 static const char *nn_pins[] = { // component pins 102 %for @c in @nlin_elements:\ 103 "@c", 104 %end 0 105 }; 106 static const char *m = "@method"; 107 static const char *pvars[] = {@pot_vars}; 108 static double pvalues[] = {@pot}; 109 static const char *ol[] = {@out_labels}; 110 static const char *c = "@comment"; 111 if (name) *name = n; 112 if (data_size) *data_size = sizeof(creal); 113 if (samplerate) *samplerate = @fs; 114 if (shapes) *shapes = sz; 115 if (comp_sz) *comp_sz = nn_sz; 116 if (pins) *pins = nn_pins; 117 if (comp_names) *comp_names = nn_name; 118 if (method) *method = m; 119 if (pot_vars) *pot_vars = pvars; 120 if (pot) *pot = pvalues; 121 if (out_labels) *out_labels = ol; 122 if (comment) *comment = c; 123} 124%end 125 126static creal x0_data[] = {@x0_data}; 127%if (@dev_interface) 128static creal v0_data[] = {@v0_data}; 129static creal p0_data[] = {@p0_data}; 130static creal o0_data[] = {@o0_data}; 131static creal op_data[] = {@op_data}; 132 133extern "C" __attribute__ ((visibility ("default"))) 134void get_dc(creal *v0, creal *x0, creal *p0, creal *o0, creal *op) { 135 if (v0) { 136 for (int i = 0; i < @nn; i++) { 137 v0[i] = v0_data[i]; 138 } 139 } 140 if (x0) { 141 for (int i = 0; i < @nx; i++) { 142 x0[i] = x0_data[i]; 143 } 144 } 145 if (p0) { 146 for (int i = 0; i < @nni; i++) { 147 p0[i] = p0_data[i]; 148 } 149 } 150 if (o0) { 151 for (int i = 0; i < @no; i++) { 152 o0[i] = o0_data[i]; 153 } 154 } 155 if (op) { 156 for (int i = 0; i < @ni; i++) { 157 op[i] = op_data[i]; 158 } 159 } 160} 161 162extern "C" __attribute__ ((visibility ("default"))) 163void get_info(creal *v, creal *x, creal *minval, creal *maxval, int *info, int *nfev, creal *fnorm) { 164 Map<Matrix<creal, @nn, 1> > V(v); 165 V = g_v; 166 Map<Matrix<creal, @nx, 1> > X(x); 167 X = g_x; 168 Map<Matrix<creal, @nni, 1> > Mi(minval); 169 Mi = g_min; 170 Map<Matrix<creal, @nni, 1> > Ma(maxval); 171 Ma = g_max; 172 *info = g_info; 173 *nfev = g_nfev; 174 *fnorm = g_fnorm; 175} 176 177extern "C" __attribute__ ((visibility ("default"))) 178void set_state(creal *v, creal *x) { 179 Map<Matrix<creal, @nn, 1> > V(v); 180 g_v = V; 181 Map<Matrix<creal, @nx, 1> > X(x); 182 g_x = X; 183} 184%end 185 186#define real realtype // real conflicts with Eigen::real of new eigen library version 187typedef double real; 188%if (@method == "table") 189%include ("intpp.h") 190#define NO_INTPP_INCLUDES 191%include ("intpp.cc") 192@extra_sources.intpp_inst 193%%@extra_sources.data_h 194@extra_sources.data_c 195%end 196 197@global_matrices 198 199static Matrix<creal, @npl, 1> last_pot; 200 201@struct_def 202 203%if (@dev_interface || @npl) 204void calc_inv_update(const creal *pot, nonlin_param& par) { 205 Map<const Matrix<creal, @npl, 1> >pm(pot); 206 last_pot = pm; 207 @update_pot 208} 209%end 210%if (@dev_interface) 211nonlin_param par@nonlin_mat_list; 212 213extern "C" __attribute__ ((visibility ("default"))) 214void calc_inv_update(const creal *pot) { 215 calc_inv_update(pot, par); 216} 217%end 218 219@nonlin_code 220 221%if (@dev_interface) 222extern "C" __attribute__ ((visibility ("default"))) 223int calc_stream(creal *u, creal *o, int n, int ii) { 224 Matrix<creal, @nn, 1> mi; 225%if (@nn) 226 g_min = Matrix<creal, @nni, 1>::Constant(HUGE_VAL); 227 g_max = Matrix<creal, @nni, 1>::Constant(-HUGE_VAL); 228 g_fnorm = 0; 229 par.v = &g_v; 230 par.i = &mi; 231 Array<creal, @nni, 1> p_val; 232 par.p_val = &p_val; 233 creal fnorm; 234 par.fnorm = &fnorm; 235 Matrix<creal, @nn, 1> mp; 236 par.p = ∓ 237%end 238 int nu = @ni; 239 if (ii >= 0) { 240 nu += 1; 241 } 242 for (int j = 0; j < n; j++) { 243#define GET_U (u+j*nu) 244#define DTP_U creal 245 @pre_filter 246%if (@nn) 247 Matrix<creal, @mp_cols, 1> dp; 248 dp << g_x, Map<Matrix<creal,@ni,1> >(GET_U); 249 @gen_mp 250 int ret = nonlin::nonlin_solve(par); 251 if (fnorm > g_fnorm) { 252 g_fnorm = fnorm; 253 } 254 if (ret != 0) { 255 return ret; 256 } 257 g_min = g_min.min(p_val.array()); 258 g_max = g_max.max(p_val.array()); 259 if (ii >= 0) { 260 mi(ii) += GET_U[@ni]; 261 } 262%end 263 Matrix<creal, @m_cols, 1> d; 264%if (@nn) 265 d << g_x, Map<Matrix<creal,@ni,1> >(GET_U), mi@iblock; 266%else 267 d << g_x, Map<Matrix<creal,@ni,1> >(GET_U); 268%end 269%if (@nx) 270 Matrix<creal, @nx, 1>& xn = g_x; 271 @gen_xn 272%end 273 Map<Matrix<creal, @no, 1> > xo(o+@no*j); 274 @gen_xo 275#undef GET_U 276#undef DTP_U 277 } 278 return 0; 279} 280 281extern "C" __attribute__ ((visibility ("default"))) 282int calc(creal *u, creal *x, creal *v, creal *x_new, creal *o, int *info, int *nfev, creal *fnorm) { 283#define GET_U (u) 284#define DTP_U creal 285 @pre_filter 286 int ret = 0; 287 Matrix<creal, @nn, 1> mi; 288%if (@nn) 289 par.fnorm = fnorm; 290 par.i = &mi; 291 Matrix<creal, @mp_cols, 1> dp; 292 dp << Map<Matrix<creal,@nx,1> >(x), Map<Matrix<creal,@ni,1> >(u); 293 Matrix<creal, @nn, 1> mp; 294 par.p = ∓ 295 Map<Matrix<creal, @nn, 1> >Mv(v); 296 par.v = &Mv; 297 Array<creal, @nni, 1> p_val; 298 par.p_val = &p_val; 299 @gen_mp 300 ret = nonlin::nonlin(par); 301%else 302 *info = 1; 303 *nfev = 0; 304 *fnorm = 0; 305%end 306 Matrix<creal, @m_cols, 1> d; 307 d << Map<Matrix<creal,@nx,1> >(x), Map<Matrix<creal,@ni,1> >(u), mi@iblock; 308 Map<Matrix<creal, @nx, 1> > xn(x_new); 309 @gen_xn 310 Map<Matrix<creal, @no, 1> > xo(o); 311 @gen_xo 312 return ret; 313#undef GET_U 314#undef DTP_U 315} 316%end 317 318%if (@resample) 319#include <zita-resampler/resampler.h> 320 321class FixedRateResampler { 322private: 323 Resampler r_up, r_down; 324 int inputRate, outputRate; 325 int last_in_count; 326public: 327 int setup(int _inputRate, int _outputRate); 328 int up(int count, float *input, float *output); 329 void down(float *input, float *output); 330 int max_out_count(int in_count) { 331 return static_cast<int>(ceil((in_count*static_cast<double>(outputRate))/inputRate)); } 332}; 333 334int FixedRateResampler::setup(int _inputRate, int _outputRate) 335{ 336 const int qual = 16; // resulting in a total delay of 2*qual (0.7ms @44100) 337 inputRate = _inputRate; 338 outputRate = _outputRate; 339 if (inputRate == outputRate) { 340 return 0; 341 } 342 // upsampler 343 int ret = r_up.setup(inputRate, outputRate, 1, qual); 344 if (ret) { 345 return ret; 346 } 347 // k == filtlen() == 2 * qual 348 // pre-fill with k-1 zeros 349 r_up.inp_count = r_up.filtlen() - 1; 350 r_up.out_count = 1; 351 r_up.inp_data = r_up.out_data = 0; 352 r_up.process(); 353 // downsampler 354 ret = r_down.setup(outputRate, inputRate, 1, qual); 355 if (ret) { 356 return ret; 357 } 358 // k == filtlen() == 2 * qual * fact 359 // pre-fill with k-2 zeros 360 r_down.inp_count = r_down.filtlen() - 2; 361 r_down.out_count = 1; 362 r_down.inp_data = r_down.out_data = 0; 363 r_down.process(); 364 return 0; 365} 366 367int FixedRateResampler::up(int count, float *input, float *output) 368{ 369 if (inputRate == outputRate) { 370 memcpy(output, input, count*sizeof(float)); 371 r_down.out_count = count; 372 return count; 373 } 374 r_up.inp_count = count; 375 r_down.out_count = count+1; // +1 == trick to drain input 376 r_up.inp_data = input; 377 int m = max_out_count(count); 378 r_up.out_count = m; 379 r_up.out_data = output; 380 r_up.process(); 381 assert(r_up.inp_count == 0); 382 assert(r_up.out_count <= 1); 383 r_down.inp_count = m - r_up.out_count; 384 return r_down.inp_count; 385} 386 387void FixedRateResampler::down(float *input, float *output) 388{ 389 if (inputRate == outputRate) { 390 memcpy(output, input, r_down.out_count*sizeof(float)); 391 return; 392 } 393 r_down.inp_data = input; 394 r_down.out_data = output; 395 r_down.process(); 396 assert(r_down.inp_count == 0); 397 assert(r_down.out_count == 1); 398} 399 400FixedRateResampler smp; 401%end 402 403class DKPlugin: public PluginDef { 404public: 405 float pots[@npl+@add_npl]; 406private: 407 creal pots_last[@npl+@add_npl]; 408 Matrix<creal, @nx, 1> x_last; 409 @DKPlugin_fields 410public: 411 EIGEN_MAKE_ALIGNED_OPERATOR_NEW; 412 DKPlugin(); 413 static void init(unsigned int samplingFreq, PluginDef *plugin); 414 static void process(int count, float *input, float *output, PluginDef *plugin); 415 static int registerparam(const ParamReg& reg); 416 static int uiloader(const UiBuilder& builder, int form); 417 static void del_instance(PluginDef *plugin); 418}; 419 420DKPlugin::DKPlugin(): 421 PluginDef(), pots(), pots_last(), x_last()@DKPlugin_init { 422 version = PLUGINDEF_VERSION; 423 flags = 0; 424 id = @plugindef.s_id; 425 name = @plugindef.l_name; 426 groups = 0; 427 description = @plugindef.l_description; 428 category = @plugindef.l_category; 429 shortname = @plugindef.l_shortname; 430 mono_audio = process; 431 set_samplerate = init; 432 register_params = registerparam; 433 load_ui = uiloader; 434 delete_instance = del_instance; 435 for (int i = 0; i < @nx; i++) { 436 x_last(i) = x0_data[i]; 437 } 438} 439 440#define PARAM(p) ("@id" "." p) 441 442int DKPlugin::registerparam(const ParamReg& reg) { 443 %if (@regs) 444 DKPlugin& self = *static_cast<DKPlugin*>(reg.plugin); 445 %end 446 %for @r in @regs: 447 reg.registerFloatVar(PARAM("@r.id"), N_("@r.name"), "S", N_("@r.desc"), &self.pots[@r.varidx], 0.5, 0, 1, 0.01, nullptr); 448 %end 449 return 0; 450} 451 452void DKPlugin::init(unsigned int samplingFreq, PluginDef *plugin) { 453%if (@resample) 454 smp.setup(samplingFreq, @fs); 455%end 456%if (@filter_init) 457 DKPlugin& self = *static_cast<DKPlugin*>(plugin); 458 @filter_init 459%end 460} 461 462void DKPlugin::process(int n, float *u, float *o, PluginDef *plugin) { 463 DKPlugin& self = *static_cast<DKPlugin*>(plugin); 464%if (@npl || @add_npl) 465 creal t[@npl+@add_npl]; 466 @calc_pots 467%end 468 @process_add 469// start copied and modified code 470 Matrix<creal, @nn, 1> mi; 471%if (@nn) 472%% g_min = Matrix<creal, @nni, 1>::Constant(HUGE_VAL); 473%% g_max = Matrix<creal, @nni, 1>::Constant(-HUGE_VAL); 474%% g_fnorm = 0; 475 creal fnorm; 476 Matrix<creal, @nn, 1> mp; 477 Array<creal, @nni, 1> p_val; 478 nonlin_param par@nonlin_mat_list_calc; 479%end 480%if (@resample) 481 float buf[smp.max_out_count(n)]; 482 n = smp.up(n, u, buf); 483#define GET_U (buf+j*@ni) 484%else 485#define GET_U (u+j*@ni) 486%end 487 for (int j = 0; j < n; j++) { 488#define DTP_U float 489 @pre_filter 490%if (@npl) 491 for (int k = 0; k < @npl; k++) { 492 self.pots_last[k] = @timecst * t[k] + (1-@timecst) * self.pots_last[k]; 493 } 494 calc_inv_update(self.pots_last, par); 495%end 496%if (@nn) 497 Matrix<creal, @mp_cols, 1> dp; 498 dp << self.x_last, Map<Matrix<float,@ni,1> >(GET_U).cast<creal>(); 499 @gen_mp 500 nonlin::nonlin(par); 501%% int ret = nonlin::nonlin_solve(par); 502%% if (fnorm > g_fnorm) { 503%% g_fnorm = fnorm; 504%% } 505%% if (ret != 0) { 506%% return; 507%% } 508%end 509 Matrix<creal, @m_cols, 1> d; 510 d << self.x_last, Map<Matrix<float,@ni,1> >(GET_U).cast<creal>(), mi@iblock; 511%if (@nx) 512 Matrix<creal, @nx, 1>& xn = self.x_last; 513 @gen_xn 514%end 515%if (@resample) 516 Map<Matrix<float, @no, 1> > xo(buf+@no*j); 517%else 518 Map<Matrix<float, @no, 1> > xo(o+@no*j); 519%end 520 @gen_xo_float 521 @post_filter 522#undef GET_U 523#undef DTP_U 524 } 525%if (@resample) 526 smp.down(buf, o); 527%end 528 @post_process 529// end copied code 530} 531 532int DKPlugin::uiloader(const UiBuilder& b, int form) { 533 if (!(form & UI_FORM_STACK)) { 534 return -1; 535 } 536 %parse ("module_ui_template") 537 return 0; 538} 539 540void DKPlugin::del_instance(PluginDef *p) 541{ 542 delete static_cast<DKPlugin*>(p); 543} 544 545%if (@dev_interface) 546extern "C" __attribute__ ((visibility ("default"))) 547int get_gx_plugin(unsigned int idx, PluginDef **pplugin) 548{ 549 const int count = 1; 550 if (!pplugin) { 551 return count; 552 } 553 switch (idx) { 554 case 0: *pplugin = new DKPlugin; return count; 555 default: *pplugin = 0; return -1; 556 } 557} 558%else 559namespace pluginlib { namespace @plugindef.namespace { 560PluginDef *plugin() { 561 return new DKPlugin; 562} 563}} 564%end 565 566%if (@{plugindef.lv2_plugin_type}) 567%parse ("lv2_interface") 568%end 569""") 570 571lv2_manifest = Template(""" 572\@prefix lv2: <http://lv2plug.in/ns/lv2core#> . 573\@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . 574 575<http://guitarix.sourceforge.net/plugins/@id#@{plugindef.lv2_versioned_id}> 576 a lv2:Plugin ; 577 lv2:binary <@{plugindef.lv2_versioned_id}.so> ; 578 rdfs:seeAlso <@{plugindef.lv2_versioned_id}.ttl> . 579""") 580 581lv2_ttl = Template(""" 582\@prefix doap: <http://usefulinc.com/ns/doap#> . 583\@prefix foaf: <http://xmlns.com/foaf/0.1/> . 584\@prefix lv2: <http://lv2plug.in/ns/lv2core#> . 585\@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . 586\@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . 587\@prefix guiext: <http://lv2plug.in/ns/extensions/ui#>. 588 589<http://guitarix.sourceforge.net#devel> 590 a foaf:Group ; 591 foaf:name "Guitarix team" ; 592 foaf:mbox <mailto:guitarix-developer\@lists.sourceforge.net> ; 593 rdfs:seeAlso <http://guitarix.sourceforge.net> . 594 595<http://guitarix.sourceforge.net/plugins/@id> 596 a doap:Project ; 597 doap:maintainer <http://guitarix.sourceforge.net#devel> ; 598 doap:name "@{plugindef.name}" . 599 600<http://guitarix.sourceforge.net/plugins/@id#@{plugindef.lv2_versioned_id}> 601 a lv2:Plugin , 602 lv2:@{plugindef.lv2_plugin_type} ; 603 doap:maintainer <http://guitarix.sourceforge.net#devel> ; 604 doap:name "@{plugindef.name}"; 605 doap:license <http://usefulinc.com/doap/licenses/gpl> ; 606 lv2:project <http://guitarix.sourceforge.net/plugins/@id> ; 607 lv2:optionalFeature lv2:hardRTCapable ; 608 lv2:minorVersion @{plugindef.lv2_minor_version}; 609 lv2:microVersion @{plugindef.lv2_micro_version}; 610 611 lv2:port\ 612%for @p in @lv2_ports:\ 613 [ 614 a @{p.type_list} ; 615 lv2:index @{p.index} ; 616 lv2:symbol "@{p.symbol}" ; 617 lv2:name "@{p.name}" ; 618%if (@{p.control_index} >= 0)\ 619 lv2:default @{p.default} ; 620 lv2:minimum @{p.minimum} ; 621 lv2:maximum @{p.maximum} ; 622%end 623 ]%if(@velocityHasNext),%end\ 624%end. 625""") 626 627lv2_interface = Template(""" 628#include "lv2/lv2plug.in/ns/lv2core/lv2.h" 629 630#define LV2_PLUGIN_URI "http://guitarix.sourceforge.net/plugins/@id#@{plugindef.lv2_versioned_id}" 631 632typedef enum { 633%for @p in @lv2_ports:\ 634 PORT_@{p.symbol} = @{p.index}, 635%end 636} PortIndex; 637 638class LV2_DKPlugin: public DKPlugin { 639public: 640 // Port buffers 641 float* ports[@{lv2_ports.port_count()}]; 642public: 643 LV2_DKPlugin(): DKPlugin() {} 644}; 645 646static LV2_Handle 647instantiate(const LV2_Descriptor* descriptor, 648 double rate, 649 const char* bundle_path, 650 const LV2_Feature* const* features) 651{ 652 LV2_DKPlugin *p = new LV2_DKPlugin; 653 p->set_samplerate(rate, p); 654 return static_cast<LV2_Handle>(p); 655} 656 657static void 658connect_port(LV2_Handle instance, 659 uint32_t port, 660 void* data) 661{ 662 static_cast<LV2_DKPlugin*>(instance)->ports[port] = static_cast<float*>(data); 663} 664 665static void 666activate(LV2_Handle instance) 667{ 668} 669 670static void 671run(LV2_Handle instance, uint32_t n_samples) 672{ 673 LV2_DKPlugin* p = static_cast<LV2_DKPlugin*>(instance); 674 675%for @p in @lv2_ports:\ 676%if (@{p.control_index} >= 0)\ 677 p->pots[@{p.control_index}] = *(p->ports[@{p.index}]); 678%end 679%end 680%if (@ni == 1 && @no == 1) 681 p->process(n_samples, p->ports[0], p->ports[1], p); 682%else 683 p->process(n_samples, p->ports[0], p->ports[1], p->ports[2], p->ports[3], p); 684%end 685} 686 687static void 688deactivate(LV2_Handle instance) 689{ 690} 691 692static void 693cleanup(LV2_Handle instance) 694{ 695 LV2_DKPlugin* p = static_cast<LV2_DKPlugin*>(instance); 696 p->delete_instance(p); 697} 698 699static const void* 700extension_data(const char* uri) 701{ 702 return NULL; 703} 704 705static const LV2_Descriptor descriptor = { 706 LV2_PLUGIN_URI, 707 instantiate, 708 connect_port, 709 activate, 710 run, 711 deactivate, 712 cleanup, 713 extension_data 714}; 715 716extern "C" 717LV2_SYMBOL_EXPORT 718const LV2_Descriptor* 719lv2_descriptor(uint32_t index){ 720 switch (index){ 721 case 0: 722 return &descriptor; 723 default: 724 return NULL; 725 } 726} 727 728 729 730""") 731 732c_template_calc_nonlin = Template(""" 733%if (@dev_interface) 734extern "C" __attribute__ ((visibility ("default"))) 735int calc_@{namespace}(int n, creal *p, creal *i, creal *v, int *info, int *nfev, creal *fnorm) { 736 int ret = 0; 737 Matrix<creal, @g_nn, 1> mp; 738 Matrix<creal, @g_nn, 1> mi; 739 Map<Matrix<creal, @g_nn, 1> >Mv(v); 740 Array<creal, @g_nni, 1> p_val; 741 nonlin_param par@nonlin_mat_list; 742 for (int k = 0; k < n; k++) { 743 calc_inv_update(p+k*(@nni+@npl), par); 744 mp@pblockV << Map<Matrix<creal, @nni, 1> >(p+k*(@nni+@npl)+@npl); 745 ret = @namespace::nonlin_solve(par); 746 Map<Matrix<creal, @nno, 1> >(i+k*@nno) << mi@iblockV; 747 } 748 return ret; 749} 750%end 751""") 752 753c_template_nonlin_func_hybr = Template(""" 754static int fcn(void *p, int n, const creal *v, creal *fvec, int iflag ) { 755 nonlin_param& par = *static_cast<nonlin_param *>(p); 756 @expression 757 return 0; 758} 759""") 760 761c_template_nonlin_func_lm = Template(""" 762static int fcn(void *p, int m, int n, const creal *v, creal *fvec, int iflag ) { 763 nonlin_param& par = *static_cast<nonlin_param *>(p); 764 @expression 765 return 0; 766} 767""") 768 769c_template_nonlin_func_hybrCC = Template(""" 770typedef int root_fcn(void*p, const creal *v, creal *fvec, int iflag); 771static int fcn(void *p, const creal *v, creal *fvec, int iflag) { 772 nonlin_param& par = *static_cast<nonlin_param *>(p); 773 @expression 774 return 0; 775} 776""") 777 778c_template_nonlin_solver_hybr = Template(""" 779static int nonlin(struct nonlin_param &par) { 780 int maxfev, mode, nprint, ldfjac; 781 creal xtol, epsfcn, factor; 782 creal __attribute__((aligned(16))) fvec[@nn]; 783 creal __attribute__((aligned(16))) fjac[@nn*@nn]; 784 creal __attribute__((aligned(16))) qtf[@nn]; 785 creal __attribute__((aligned(16))) wa1[@nn]; 786 creal __attribute__((aligned(16))) wa2[@nn]; 787 creal __attribute__((aligned(16))) wa3[@nn]; 788 creal __attribute__((aligned(16))) wa4[@nn]; 789 creal diag[@nn] = {%for @j in @solver_diag:@j,%end}; 790 int ml, mu, lr; 791 creal r[(@nn*(@nn+1))/2]; 792 lr = (@nn*(@nn+1))/2; 793 ml = @nn-1; /* unbanded jacobian */ 794 mu = @nn-1; /* unbanded jacobian */ 795 ldfjac = @nn; 796 797 /* parameter */ 798 xtol = @solver_xtol; 799 maxfev = @solver_maxfev; 800 epsfcn = 0.; 801 //mode = 2; /* explicit variable scaling with diag */ 802 mode = 1; /* automatic variable scaling */ 803 factor = @solver_factor; 804 nprint = 0; 805 /**/ 806 807 @setup 808 @store_p 809 @p_transform 810 *par.info = __cminpack_func__(hybrd)( 811 fcn, &par, @nn, @var_v_ref, fvec, xtol, maxfev, ml, mu, epsfcn, diag, 812 mode, factor, nprint, par.nfev, fjac, ldfjac, r, lr, qtf, wa1, wa2, wa3, wa4); 813 *par.fnorm = __cminpack_func__(enorm)(@nn, fvec); 814 @i_transform 815 int ret = 0; 816 if (*par.info != 1) { 817 if (!(*par.info == 5 && *par.fnorm < 1e-20)) { 818 ret = -1; 819 } 820 } 821 @cleanup 822 return ret; 823} 824""") 825 826c_template_nonlin_solver_lm = Template(""" 827static int nonlin(struct nonlin_param &par) { 828 int maxfev, mode, nprint, ldfjac; 829 creal xtol, epsfcn, factor; 830 creal __attribute__((aligned(16))) fvec[@nn]; 831 creal __attribute__((aligned(16))) fjac[@nn*@nn]; 832 creal __attribute__((aligned(16))) qtf[@nn]; 833 creal __attribute__((aligned(16))) wa1[@nn]; 834 creal __attribute__((aligned(16))) wa2[@nn]; 835 creal __attribute__((aligned(16))) wa3[@nn]; 836 creal __attribute__((aligned(16))) wa4[@nn]; 837 creal diag[@nn] = {%for @j in @solver_diag:@j,%end}; 838 int __attribute__((aligned(16))) ipvt[@nn]; 839 creal ftol, gtol; 840 ftol = sqrt(__cminpack_func__(dpmpar)(1)); // parameter 841 gtol = 0.; // parameter 842 ldfjac = @nn; 843 844 /* parameter */ 845 xtol = @solver_xtol; 846 maxfev = @solver_maxfev; 847 epsfcn = 0.; 848 //mode = 2; /* explicit variable scaling with diag */ 849 mode = 1; /* automatic variable scaling */ 850 factor = @solver_factor; 851 nprint = 0; 852 /**/ 853 854 @setup 855 @store_p 856 @p_transform 857 858 *par.info = __cminpack_func__(lmdif)( 859 fcn, &par, @nn, @nn, @var_v_ref, fvec, ftol, xtol, gtol, maxfev, epsfcn, diag, 860 mode, factor, nprint, par.nfev, fjac, ldfjac, ipvt, qtf, wa1, wa2, wa3, wa4); 861 *par.fnorm = __cminpack_func__(enorm)(@nn, fvec); 862 @i_transform 863 @cleanup 864 return (*par.info < 1 || *par.info > 4) ? -1 : 0; 865} 866""") 867 868c_template_nonlin_solver_hybrCC = Template(""" 869%include ("hybrd.cc") 870 871static int nonlin(struct nonlin_param &par) { 872 int maxfev, mode, nprint, ldfjac; 873 creal xtol, epsfcn, factor; 874 creal __attribute__((aligned(16))) fvec[@nn]; 875 creal __attribute__((aligned(16))) fjac[@nn*@nn]; 876 creal __attribute__((aligned(16))) qtf[@nn]; 877 creal __attribute__((aligned(16))) wa1[@nn]; 878 creal __attribute__((aligned(16))) wa2[@nn]; 879 creal __attribute__((aligned(16))) wa3[@nn]; 880 creal __attribute__((aligned(16))) wa4[@nn]; 881 creal diag[@nn] = {%for @j in @solver_diag:@j,%end}; 882 int ml, mu, lr; 883 creal r[(@nn*(@nn+1))/2]; 884 lr = (@nn*(@nn+1))/2; 885 ml = @nn-1; /* unbanded jacobian */ 886 mu = @nn-1; /* unbanded jacobian */ 887 ldfjac = @nn; 888 889 /* parameter */ 890 xtol = @solver_xtol; 891 maxfev = @solver_maxfev; 892 epsfcn = 0.; 893 //mode = 2; /* explicit variable scaling with diag */ 894 mode = 1; /* automatic variable scaling */ 895 factor = @solver_factor; 896 nprint = 0; 897 /**/ 898 899 @setup 900 @store_p 901 @p_transform 902 903 *par.info = hybrdX<@nn>(fcn, &par, @var_v_ref, fvec, xtol, maxfev, ml, mu, epsfcn, 904 diag, mode, factor, nprint, par.nfev, fjac, ldfjac, r, lr, 905 qtf, wa1, wa2, wa3, wa4); 906 *par.fnorm = enorm<@nn>(fvec); 907 @i_transform 908 int ret = 0; 909 if (*par.info != 1) { 910 if (!(*par.info == 5 && *par.fnorm < 1e-20)) { 911 ret = -1; 912 } 913 } 914 @cleanup 915 return ret; 916} 917""") 918 919c_template_nonlin_chained = Template(""" 920namespace @namespace { 921@global_data_def 922 923static int nonlin(struct nonlin_param &par) { 924 @chained_code 925} 926 927%if (@dev_interface) 928static inline int nonlin_solve(nonlin_param& par) { 929 return nonlin(par); 930} 931%end 932} // end namespace @namespace 933%if (@extern_nonlin) 934%parse ("c_template_calc_nonlin") 935%end 936""") 937 938c_template_nonlin_solver = Template(""" 939namespace @namespace { 940@global_data_def 941 942@fcn_def 943 944@nonlin_def 945 946%if (@dev_interface) 947static Matrix<creal, @nni, 1> last_good; 948static Matrix<creal, @nn, 1> last_v0; 949 950int nonlin_homotopy(nonlin_param& par, creal f) { 951 Matrix<creal, @nni, 1> end = @par_p; 952 @par_p = last_good + (@par_p - last_good) * f; 953 @par_v = last_v0; 954 int ret = nonlin(par); 955 @par_p = end; 956 if (ret != 0) { 957 return ret; 958 } 959 last_v0 = @par_v; 960 return 0; 961} 962 963static inline int nonlin_solve(nonlin_param& par) { 964 @v0_guess 965 int ret = nonlin(par); 966 if (ret != 0) { 967 std::list<creal> points; 968 points.push_back(0); 969 points.push_back(0.5); 970 points.push_back(1); 971 for (int j = 0; j < @solver_max_homotopy_iter; j++) { 972 std::list<creal>::iterator it = points.begin(); 973 ++it; 974 ret = nonlin_homotopy(par, *it); 975 if (ret != 0) { 976 points.insert(it, (*points.begin()+*it)/2); 977 continue; 978 } 979 if (points.size() == 2) { 980 break; 981 } 982 points.erase(points.begin()); 983 } 984 if (ret != 0) { 985 return ret; 986 } 987 } 988 last_good = @par_p; 989 last_v0 = @par_v; 990 return 0; 991} 992%end 993} // end namespace @namespace 994 995%if (@extern_nonlin) 996%parse ("c_template_calc_nonlin") 997%end 998""") 999 1000c_template_table = Template(""" 1001namespace @namespace { 1002static inline int nonlin(nonlin_param& par) { 1003 @call 1004 return 0; 1005} 1006 1007%if (@dev_interface) 1008static inline int nonlin_solve(nonlin_param& par) { 1009 return nonlin(par); 1010} 1011%end 1012 1013%parse ("c_template_calc_nonlin") 1014} // end @namespace 1015""") 1016 1017# 1018#-mavx -ffast-math 1019# 1020# ffast-math seems to trigger a compiler error on gcc 4.7.3 1021# according to documentation it expands into list of settings, including 1022# funsafe-math-optimizations, which seems to be responsible for the bug. 1023# But funsafe-math-optimizations in turn just expands into another list of 1024# settings. When using the expanded list of settings the bug is gone (?!). 1025# 1026# maybe -mavx is the culprit (removed for now)?? 1027# 1028build_script_template = Template("""\ 1029#! /bin/bash 1030cd `dirname $0` 1031fname="${1-@sourcename}" 1032lname="${2-@soname}" 1033lname_="${2-@soname_}" 1034mo="-fwrapv -ffast-math -msse2" 1035#mo="-fwrapv -fno-math-errno -ffinite-math-only -fno-rounding-math" 1036#mo="$mo -fno-signaling-nans -fcx-limited-range -fno-signed-zeros" 1037#mo="$mo -fno-trapping-math -fassociative-math -freciprocal-math" 1038: ${CC:=c++} 1039%if (@debug) 1040dbg="-g -O2" 1041%else 1042dbg="-O2 -Wl,--strip-all -DNDEBUG" 1043%end 1044co="-shared -fPIC -Wall -fvisibility=hidden" 1045lo="-Wl,-O1,-Bsymbolic-functions,-z,relro" 1046libs="@libraries" 1047inc="@includes" 1048def="@defines" 1049opt="-fno-stack-protector" 1050set -e 1051%if (@optimize) 1052$CC $co $lo $mo $opt -fprofile-arcs $dbg $CFLAGS $def $inc "$fname" -o "$lname_" $libs 1053python t.py 1054$CC $co $lo $mo $opt -fprofile-use $dbg $CFLAGS $def $inc "$fname" -o "$lname" $libs 1055%else 1056$CC $co $lo $mo $opt $dbg $CFLAGS $def $inc "$fname" -o "$lname" $libs 1057%end 1058""") 1059 1060faust_filter_template = Template("""\ 1061%if (@build_script)\ 1062// generated by @build_script 1063%else\ 1064// generated automatically 1065%end 1066// DO NOT MODIFY! 1067declare id "@plugindef.id"; 1068declare name "@plugindef.name"; 1069declare category "@plugindef.category"; 1070%if (@plugindef.shortname)\ 1071declare shortname "@plugindef.shortname"; 1072%end 1073%if (@plugindef.description)\ 1074declare description "@plugindef.description"; 1075%end 1076%if (@plugindef.samplerate)\ 1077declare samplerate "@plugindef.samplerate"; 1078%end 1079%if (@plugindef.oversample)\ 1080declare oversample "@plugindef.oversample"; 1081%end 1082%if (@plugindef.fixedrate)\ 1083declare samplerate "@plugindef.fixedrate"; 1084%end 1085 1086import("stdfaust.lib"); 1087//TABLE 1088process = pre : fi.iir((@b_list),(@a_list)) with { 1089 LogPot(a, x) = ba.if(a, (exp(a * x) - 1) / (exp(a) - 1), x); 1090 Inverted(b, x) = ba.if(b, 1 - x, x); 1091 s = 0.993; 1092 fs = float(ma.SR); 1093 pre = @pre_filter; 1094 1095%for @sl in @sliders: 1096%if (@sl.loga) 1097 @sl.id = vslider("@sl.id[name:@sl.name][style:knob]", 0.5, 0, 1, 0.01) : Inverted(@sl.inv) : LogPot(@sl.loga) : si.smooth(s); 1098%else 1099 @sl.id = vslider("@sl.id[name:@sl.name][style:knob]", 0.5, 0, 1, 0.01) : Inverted(@sl.inv) : si.smooth(s); 1100%end 1101%end 1102 1103 @coeffs 1104}; 1105""") 1106 1107module_ui_template = Template(""" 1108b.openHorizontalhideBox(""); 1109%if (@have_master_slider) 1110 b.create_master_slider(PARAM("@master_slider_id"), "@master_slider_id"); 1111%end 1112b.closeBox(); 1113b.openHorizontalBox(""); 1114%for @k in @knob_ids: 1115 b.create_small_rackknobr(PARAM("@k"), "@k"); 1116%end 1117b.closeBox(); 1118""") 1119 1120faust_simple_filter_template = Template("""\ 1121//TABLE 1122process = pre : fi.iir((@b_list),(@a_list)) with { 1123 LogPot(a, x) = ba.if(a, (exp(a * x) - 1) / (exp(a) - 1), x); 1124 Inverted(b, x) = ba.if(b, 1 - x, x); 1125 s = 0.993; 1126 fs = float(ma.SR); 1127 pre = @pre_filter; 1128 1129%for @sl in @sliders: 1130%if (@sl.loga) 1131 @sl.id = vslider("@sl.id[name:@sl.name][style:knob]", 0.5, 0, 1, 0.01) : Inverted(@sl.inv) : LogPot(@sl.loga) : si.smooth(s); 1132%else 1133 @sl.id = vslider("@sl.id[name:@sl.name][style:knob]", 0.5, 0, 1, 0.01) : Inverted(@sl.inv) : si.smooth(s); 1134%end 1135%end 1136 1137 @coeffs 1138}; 1139""") 1140 1141module_simple_ui_template = Template(""" 1142b.openHorizontalBox(""); 1143%for @k in @knob_ids: 1144 b.create_small_rackknobr(PARAM("@k"), "@k"); 1145%end 1146b.closeBox(); 1147""") 1148 1149faust_filter_dry_wet_template = Template("""\ 1150%if (@build_script)\ 1151// generated by @build_script 1152%else\ 1153// generated automatically 1154%end 1155// DO NOT MODIFY! 1156declare id "@plugindef.id"; 1157declare name "@plugindef.name"; 1158declare category "@plugindef.category"; 1159%if (@plugindef.shortname)\ 1160declare shortname "@plugindef.shortname"; 1161%end 1162%if (@plugindef.description)\ 1163declare description "@plugindef.description"; 1164%end 1165 1166import("stdfaust.lib"); 1167//TABLE 1168process = pre : _<:*(dry),(*(wet) : fi.iir((@b_list),(@a_list))):>_ with { 1169 LogPot(a, x) = ba.if(a, (exp(a * x) - 1) / (exp(a) - 1), x); 1170 Inverted(b, x) = ba.if(b, 1 - x, x); 1171 s = 0.993; 1172 fs = float(ma.SR); 1173 pre = @pre_filter; 1174 wet = vslider("wet_dry[name:wet/dry][tooltip:percentage of processed signal in output signal]", 100, 0, 100, 1) : /(100); 1175 dry = 1 - wet; 1176 1177%for @sl in @sliders: 1178%if (@sl.loga) 1179 @sl.id = vslider("@sl.id[name:@sl.name][style:knob]", 0.5, 0, 1, 0.01) : Inverted(@sl.inv) : LogPot(@sl.loga) : si.smooth(s); 1180%else 1181 @sl.id = vslider("@sl.id[name:@sl.name][style:knob]", 0.5, 0, 1, 0.01) : Inverted(@sl.inv) : si.smooth(s); 1182%end 1183%end 1184 1185 @coeffs 1186}; 1187""") 1188 1189module_ui_dry_wet_template = Template(""" 1190b.openHorizontalhideBox(""); 1191%if (@have_master_slider) 1192 b.create_master_slider(PARAM("@master_slider_id"), "@master_slider_id"); 1193%end 1194b.closeBox(); 1195b.openHorizontalBox(""); 1196%for @k in @knob_ids: 1197 b.create_small_rackknobr(PARAM("@k"), "@k"); 1198%end 1199 b.create_small_rackknobr(PARAM("wet_dry"), "dry/wet"); 1200b.closeBox(); 1201""") 1202 1203faust_simple_filter_dry_wet_template = Template("""\ 1204//TABLE 1205process = pre : _<:*(dry),(*(wet) : fi.iir((@b_list),(@a_list))):>_ with { 1206 LogPot(a, x) = ba.if(a, (exp(a * x) - 1) / (exp(a) - 1), x); 1207 Inverted(b, x) = ba.if(b, 1 - x, x); 1208 s = 0.993; 1209 fs = float(ma.SR); 1210 pre = @pre_filter; 1211 wet = vslider("wet_dry[name:wet/dry][tooltip:percentage of processed signal in output signal]", 100, 0, 100, 1) : /(100); 1212 dry = 1 - wet; 1213 1214 %for @sl in @sliders: 1215 @sl.id = vslider("@sl.id[name:@sl.name][style:knob]", 0.5, 0, 1, 0.01) : Inverted(@sl.inv) : LogPot(@sl.loga) : si.smooth(s); 1216 %end 1217 1218 @coeffs 1219}; 1220""") 1221 1222module_simple_ui_dry_wet_template = Template(""" 1223b.openHorizontalBox(""); 1224%for @k in @knob_ids: 1225 b.create_small_rackknobr(PARAM("@k"), "@k"); 1226%end 1227 b.create_small_rackknobr(PARAM("wet_dry"), "dry/wet"); 1228b.closeBox(); 1229""") 1230