#include "guttersynth.h" #include "plugin.h" #include "handling.h" static const char* badHandle = "guttersynth handle is not valid"; static csnd::Csound* cs = NULL; void* allocate(size_t size) { return cs->malloc(size); } void deallocate(void* item) { cs->free(item); } /* from max patch sliders: * singlegain = gain * c = damp + (matrix out) , clipped * dt = rate * gamma = q */ class GutterSynth { gutter_state* g; csnd::Table* tGain; csnd::Table* tFreq; csnd::Table* tQ; int dataSize; void update_tables() { int changed = 0; for (int b = 0; b < g->bankCount; b++) { if (memcmp(g->gains+(g->filterCount*b), tGain[b].data(), dataSize) != 0) { memcpy(g->gains+(g->filterCount*b), tGain[b].data(), dataSize); changed = 1; } if (memcmp(g->filterFreqs+(g->filterCount*b), tFreq[b].data(), dataSize) != 0) { memcpy(g->filterFreqs+(g->filterCount*b), tFreq[b].data(), dataSize); changed = 1; } if (memcmp(g->Q+(g->filterCount*b), tQ[b].data(), dataSize) != 0) { memcpy(g->Q+(g->filterCount*b), tQ[b].data(), dataSize); changed = 1; } } if (changed) { gutter_calccoeffs(g); } } }; // ibankcount, ifiltercount, igaintbls[], ifreqtbls[], iqtables[], kgamma, komega, kc, kdt, ksinglegain, kfiltersOn, ksmoothing, kdistmethod struct gutter : csnd::Plugin<1, 13> { static constexpr char const *otypes = "a"; static constexpr char const *itypes = "iii[]i[]i[]kkkkkkkk"; gutter_state* g; csnd::Table* tGain; csnd::Table* tFreq; csnd::Table* tQ; int dataSize; int init() { if (cs == NULL) cs = csound; csound->plugin_deinit(this); g = gutter_init_ca( (int)inargs[0], (int)inargs[1], csound->sr(), &allocate, &deallocate ); csnd::Vector &ftsGain = inargs.vector_data(2); csnd::Vector &ftsFreq = inargs.vector_data(3); csnd::Vector &ftsQ = inargs.vector_data(4); if (ftsGain.len() != g->bankCount) return csound->init_error("Gain tables do not match bank count"); if (ftsFreq.len() != g->bankCount) return csound->init_error("Frequency tables do not match bank count"); if (ftsQ.len() != g->bankCount) return csound->init_error("Q tables do not match bank count"); tGain = (csnd::Table*) csound->malloc(sizeof(csnd::Table) * g->bankCount); tFreq = (csnd::Table*) csound->malloc(sizeof(csnd::Table) * g->bankCount); tQ = (csnd::Table*) csound->malloc(sizeof(csnd::Table) * g->bankCount); for (int b = 0; b < g->bankCount; b++) { tGain[b].init(csound, &ftsGain[b]); tFreq[b].init(csound, &ftsFreq[b]); tQ[b].init(csound, &ftsQ[b]); } update_tables(); g->enableAudioInput = 0; dataSize = sizeof(MYFLT) * g->filterCount; return OK; } void update_tables() { int changed = 0; for (int b = 0; b < g->bankCount; b++) { if (memcmp(g->gains+(g->filterCount*b), tGain[b].data(), dataSize) != 0) { memcpy(g->gains+(g->filterCount*b), tGain[b].data(), dataSize); changed = 1; } if (memcmp(g->filterFreqs+(g->filterCount*b), tFreq[b].data(), dataSize) != 0) { memcpy(g->filterFreqs+(g->filterCount*b), tFreq[b].data(), dataSize); changed = 1; } if (memcmp(g->Q+(g->filterCount*b), tQ[b].data(), dataSize) != 0) { memcpy(g->Q+(g->filterCount*b), tQ[b].data(), dataSize); changed = 1; } } if (changed) { gutter_calccoeffs(g); } } int deinit() { csound->free(tGain); csound->free(tFreq); csound->free(tQ); gutter_cleanup(g); return OK; } int aperf() { update_tables(); // on trig? g->gamma = inargs[5]; g->omega = inargs[6]; g->c = inargs[7]; g->dt = inargs[8]; g->singleGain = inargs[9]; g->filtersOn = (int) inargs[10]; g->smoothing = inargs[11]; g->distortionMethod = inargs[12]; gutter_process_samples(g, outargs(0), nsmps); return OK; } }; #include void csnd::on_load(csnd::Csound *csound) { csnd::plugin(csound, "gutter", csnd::thread::ia); }