From 61666143e4b7ce9433e17be88a1da2e71c5d8bf1 Mon Sep 17 00:00:00 2001 From: Krzysztof Foltman Date: Fri, 15 May 2009 22:59:55 +0100 Subject: [PATCH] + Monosynth: separate out mod matrix code --- src/Makefile.am | 4 +- src/calf/Makefile.am | 2 +- src/calf/modmatrix.h | 65 +++++++++++++++++++ src/calf/modules_synths.h | 19 +----- src/calf/synth.h | 1 - src/modmatrix.cpp | 122 +++++++++++++++++++++++++++++++++++ src/monosynth.cpp | 159 ++++++++++------------------------------------ 7 files changed, 225 insertions(+), 147 deletions(-) create mode 100644 src/calf/modmatrix.h create mode 100644 src/modmatrix.cpp diff --git a/src/Makefile.am b/src/Makefile.am index cd2162a..2d334be 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,7 +51,7 @@ calfbenchmark_CXXFLAGS = $(AM_CXXFLAGS) -DTEST_OSC calfbenchmark_LDADD += libcalfgui.la endif -calf_la_SOURCES = modules.cpp modules_dsp.cpp modules_small.cpp fluidsynth.cpp giface.cpp monosynth.cpp organ.cpp osctl.cpp osctlnet.cpp plugin.cpp preset.cpp synth.cpp utils.cpp wavetable.cpp +calf_la_SOURCES = modules.cpp modules_dsp.cpp modules_small.cpp fluidsynth.cpp giface.cpp monosynth.cpp organ.cpp osctl.cpp osctlnet.cpp plugin.cpp preset.cpp synth.cpp utils.cpp wavetable.cpp modmatrix.cpp calf_la_LIBADD ?= $(FLUIDSYNTH_DEPS_LIBS) if USE_DEBUG calf_la_LDFLAGS = -rpath $(ladspadir) -avoid-version -module -lexpat -disable-static $(FLUIDSYNTH_DEPS_LIBS) @@ -68,7 +68,7 @@ calflv2gui_la_LDFLAGS = -rpath $(lv2dir) -avoid-version -module -lexpat -export- endif endif -libcalfstatic_la_SOURCES = modules.cpp modules_dsp.cpp modules_small.cpp fluidsynth.cpp giface.cpp monosynth.cpp organ.cpp osctl.cpp osctlnet.cpp preset.cpp synth.cpp utils.cpp wavetable.cpp +libcalfstatic_la_SOURCES = modules.cpp modules_dsp.cpp modules_small.cpp fluidsynth.cpp giface.cpp monosynth.cpp organ.cpp osctl.cpp osctlnet.cpp preset.cpp synth.cpp utils.cpp wavetable.cpp modmatrix.cpp libcalfstatic_la_LDFLAGS = -static -lexpat -disable-shared $(FLUIDSYNTH_DEPS_LIBS) if USE_GUI diff --git a/src/calf/Makefile.am b/src/calf/Makefile.am index 8b1dd46..bb8c897 100644 --- a/src/calf/Makefile.am +++ b/src/calf/Makefile.am @@ -3,6 +3,6 @@ noinst_HEADERS = audio_fx.h benchmark.h biquad.h buffer.h custom_ctl.h \ delay.h envelope.h fft.h fixed_point.h giface.h gui.h inertia.h jackhost.h ladspa_wrap.h loudness.h \ lv2_contexts.h lv2_data_access.h lv2_event.h lv2_progress.h lv2_polymorphic_port.h lv2_string_port.h lv2_ui.h \ lv2_uri_map.h lv2-midiport.h lv2helpers.h lv2wrap.h \ - main_win.h metadata.h modules.h modules_dev.h modules_small.h modules_synths.h modulelist.h \ + main_win.h metadata.h modmatrix.h modules.h modules_dev.h modules_small.h modules_synths.h modulelist.h \ multichorus.h onepole.h organ.h osc.h osctl.h osctlnet.h osctlserv.h plugininfo.h preset.h \ preset_gui.h primitives.h synth.h utils.h wave.h diff --git a/src/calf/modmatrix.h b/src/calf/modmatrix.h new file mode 100644 index 0000000..580e443 --- /dev/null +++ b/src/calf/modmatrix.h @@ -0,0 +1,65 @@ +/* Calf DSP Library + * Modulation matrix boilerplate code. + * + * Copyright (C) 2009 Krzysztof Foltman + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02111-1307, USA. + */ +#include "giface.h" + +namespace dsp { + +struct modulation_entry +{ + int src1, src2; + float amount; + int dest; +}; + +}; + +namespace calf_plugins { + +class mod_matrix: public table_edit_iface +{ +protected: + table_column_info table_columns[5]; + dsp::modulation_entry *matrix; + unsigned int matrix_rows; + const char **mod_src_names, **mod_dest_names; + + mod_matrix(dsp::modulation_entry *_matrix, unsigned int _rows, const char **_src_names, const char **_dest_names); +public: + virtual const table_column_info *get_table_columns(int param); + virtual uint32_t get_table_rows(int param); + virtual std::string get_cell(int param, int row, int column); + virtual void set_cell(int param, int row, int column, const std::string &src, std::string &error); + + /// Process modulation matrix, calculate outputs from inputs + inline void calculate_modmatrix(float *moddest, int moddest_count, float *modsrc) + { + for (int i = 0; i < moddest_count; i++) + moddest[i] = 0; + for (unsigned int i = 0; i < matrix_rows; i++) + { + dsp::modulation_entry &slot = matrix[i]; + if (slot.dest) + moddest[slot.dest] += modsrc[slot.src1] * modsrc[slot.src2] * slot.amount; + } + } +}; + +}; diff --git a/src/calf/modules_synths.h b/src/calf/modules_synths.h index 0918614..615d9a1 100644 --- a/src/calf/modules_synths.h +++ b/src/calf/modules_synths.h @@ -30,21 +30,15 @@ #include "synth.h" #include "envelope.h" #include "organ.h" +#include "modmatrix.h" namespace calf_plugins { #define MONOSYNTH_WAVE_BITS 12 -struct modulation_entry -{ - int src1, src2; - float amount; - int dest; -}; - /// Monosynth-in-making. Parameters may change at any point, so don't make songs with it! /// It lacks inertia for parameters, even for those that really need it. -class monosynth_audio_module: public audio_module, public line_graph_iface, public table_edit_iface +class monosynth_audio_module: public audio_module, public line_graph_iface, public mod_matrix { public: enum { mod_matrix_slots = 10 }; @@ -91,7 +85,7 @@ public: /// Smoothed channel pressure value dsp::inertia inertia_pressure; /// Rows of the modulation matrix - modulation_entry mod_matrix[mod_matrix_slots]; + dsp::modulation_entry mod_matrix_data[mod_matrix_slots]; /// Currently used velocity float velocity; /// Last value of oscillator mix ratio @@ -179,15 +173,8 @@ public: bool is_noisy(int param_no) { return param_no != par_cutoff; } /// Calculate control signals and produce step_size samples of output. void calculate_step(); - /// Process modulation matrix - void calculate_modmatrix(float *modsrc); /// Main processing function uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask); - - virtual const table_column_info *get_table_columns(int param); - virtual uint32_t get_table_rows(int param); - virtual std::string get_cell(int param, int row, int column); - virtual void set_cell(int param, int row, int column, const std::string &src, std::string &error); }; struct organ_audio_module: public audio_module, public dsp::drawbar_organ, public line_graph_iface diff --git a/src/calf/synth.h b/src/calf/synth.h index ad381c3..dc5c8eb 100644 --- a/src/calf/synth.h +++ b/src/calf/synth.h @@ -223,7 +223,6 @@ public: virtual ~basic_synth(); }; - } #endif diff --git a/src/modmatrix.cpp b/src/modmatrix.cpp new file mode 100644 index 0000000..90db2d2 --- /dev/null +++ b/src/modmatrix.cpp @@ -0,0 +1,122 @@ +/* Calf DSP Library + * Modulation matrix boilerplate code. + * + * Copyright (C) 2001-2007 Krzysztof Foltman + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ +#include +#include +#include + +using namespace std; +using namespace dsp; +using namespace calf_plugins; + +mod_matrix::mod_matrix(modulation_entry *_matrix, unsigned int _rows, const char **_src_names, const char **_dest_names) +: matrix(_matrix) +, matrix_rows(_rows) +, mod_src_names(_src_names) +, mod_dest_names(_dest_names) +{ + table_column_info tci[5] = { + { "Source", TCT_ENUM, 0, 0, 0, mod_src_names }, + { "Modulator", TCT_ENUM, 0, 0, 0, mod_src_names }, + { "Amount", TCT_FLOAT, 0, 1, 1, NULL}, + { "Destination", TCT_ENUM, 0, 0, 0, mod_dest_names }, + { NULL } + }; + assert(sizeof(table_columns) == sizeof(tci)); + memcpy(table_columns, tci, sizeof(table_columns)); +} + +const table_column_info *mod_matrix::get_table_columns(int param) +{ + return table_columns; +} + +uint32_t mod_matrix::get_table_rows(int param) +{ + return matrix_rows; +} + +std::string mod_matrix::get_cell(int param, int row, int column) +{ + assert(row >= 0 && row < (int)matrix_rows); + modulation_entry &slot = matrix[row]; + switch(column) { + case 0: // source 1 + return mod_src_names[slot.src1]; + case 1: // source 2 + return mod_src_names[slot.src2]; + case 2: // amount + return calf_utils::f2s(slot.amount); + case 3: // destination + return mod_dest_names[slot.dest]; + default: + assert(0); + return ""; + } +} + +void mod_matrix::set_cell(int param, int row, int column, const std::string &src, std::string &error) +{ + assert(row >= 0 && row < (int)matrix_rows); + modulation_entry &slot = matrix[row]; + switch(column) { + case 0: + case 1: + { + for (int i = 0; mod_src_names[i]; i++) + { + if (src == mod_src_names[i]) + { + if (column == 0) + slot.src1 = i; + else + slot.src2 = i; + error.clear(); + return; + } + } + error = "Invalid source name"; + return; + } + case 2: + { + stringstream ss(src); + ss >> slot.amount; + error.clear(); + return; + } + case 3: + { + for (int i = 0; mod_dest_names[i]; i++) + { + if (src == mod_dest_names[i]) + { + slot.dest = i; + error.clear(); + return; + } + } + error = "Invalid destination name"; + return; + } + + } +} + diff --git a/src/monosynth.cpp b/src/monosynth.cpp index 693ff47..528b011 100644 --- a/src/monosynth.cpp +++ b/src/monosynth.cpp @@ -34,17 +34,42 @@ using namespace std; float silence[4097]; +static const char *monosynth_mod_src_names[] = { + "None", + "Velocity", + "Pressure", + "ModWheel", + "Envelope", + "LFO", + NULL +}; + +static const char *monosynth_mod_dest_names[] = { + "None", + "Attenuation", + "Osc Mix Ratio (%)", + "Cutoff [ct]", + "Resonance", + "O1: Detune [ct]", + "O2: Detune [ct]", + "O1: PW (%)", + "O2: PW (%)", + NULL +}; + monosynth_audio_module::monosynth_audio_module() -: inertia_cutoff(1) +: mod_matrix(mod_matrix_data, mod_matrix_slots, monosynth_mod_src_names, monosynth_mod_dest_names) +, inertia_cutoff(1) , inertia_pitchbend(1) , inertia_pressure(64) { for (int i = 0; i < mod_matrix_slots; i++) { - mod_matrix[i].src1 = modsrc_none; - mod_matrix[i].src2 = modsrc_none; - mod_matrix[i].amount = 0.f; - mod_matrix[i].dest = moddest_none; + dsp::modulation_entry &slot = mod_matrix_data[i]; + slot.src1 = modsrc_none; + slot.src2 = modsrc_none; + slot.amount = 0.f; + slot.dest = moddest_none; } } @@ -381,7 +406,7 @@ void monosynth_audio_module::delayed_note_on() envelope.advance(); queue_note_on = -1; float modsrc[modsrc_count] = { 1, velocity, inertia_pressure.get_last(), modwheel_value, 0, last_lfov}; - calculate_modmatrix(modsrc); + calculate_modmatrix(moddest, moddest_count, modsrc); } void monosynth_audio_module::set_sample_rate(uint32_t sr) { @@ -395,18 +420,6 @@ void monosynth_audio_module::set_sample_rate(uint32_t sr) { inertia_pitchbend.ramp.set_length(crate / 30); // 1/30s } -void monosynth_audio_module::calculate_modmatrix(float *modsrc) -{ - for (int i = 0; i < moddest_count; i++) - moddest[i] = 0; - for (int i = 0; i < mod_matrix_slots; i++) - { - modulation_entry &slot = mod_matrix[i]; - if (slot.dest) - moddest[slot.dest] += modsrc[slot.src1] * modsrc[slot.src2] * slot.amount; - } -} - void monosynth_audio_module::calculate_step() { if (queue_note_on != -1) @@ -448,7 +461,7 @@ void monosynth_audio_module::calculate_step() // mod matrix // this should be optimized heavily; I think I'll do it when MIDI in Ardour 3 gets stable :> float modsrc[modsrc_count] = { 1, velocity, inertia_pressure.get(), modwheel_value, env, lfov}; - calculate_modmatrix(modsrc); + calculate_modmatrix(moddest, moddest_count, modsrc); inertia_cutoff.set_inertia(*params[par_cutoff]); cutoff = inertia_cutoff.get() * pow(2.0f, (lfov * *params[par_lfofilter] + env * fltctl * *params[par_envmod] + moddest[moddest_cutoff]) * (1.f / 1200.f)); @@ -657,111 +670,3 @@ uint32_t monosynth_audio_module::process(uint32_t offset, uint32_t nsamples, uin return 3; } -static const char *monosynth_mod_src_names[] = { - "None", - "Velocity", - "Pressure", - "ModWheel", - "Envelope", - "LFO", - NULL -}; - -static const char *monosynth_mod_dest_names[] = { - "None", - "Attenuation", - "Osc Mix Ratio (%)", - "Cutoff [ct]", - "Resonance", - "O1: Detune [ct]", - "O2: Detune [ct]", - "O1: PW (%)", - "O2: PW (%)", - NULL -}; - -const table_column_info *monosynth_audio_module::get_table_columns(int param) -{ - - static table_column_info tci[] = { - { "Source", TCT_ENUM, 0, 0, 0, monosynth_mod_src_names }, - { "Modulator", TCT_ENUM, 0, 0, 0, monosynth_mod_src_names }, - { "Amount", TCT_FLOAT, 0, 1, 1, NULL}, - { "Destination", TCT_ENUM, 0, 0, 0, monosynth_mod_dest_names }, - { NULL } - }; - return tci; -} - -uint32_t monosynth_audio_module::get_table_rows(int param) -{ - return mod_matrix_slots; -} - -std::string monosynth_audio_module::get_cell(int param, int row, int column) -{ - assert(row >= 0 && row < mod_matrix_slots); - modulation_entry &slot = mod_matrix[row]; - switch(column) { - case 0: // source 1 - return monosynth_mod_src_names[slot.src1]; - case 1: // source 2 - return monosynth_mod_src_names[slot.src2]; - case 2: // amount - return calf_utils::f2s(slot.amount); - case 3: // destination - return monosynth_mod_dest_names[slot.dest]; - default: - assert(0); - return ""; - } -} - -void monosynth_audio_module::set_cell(int param, int row, int column, const std::string &src, std::string &error) -{ - assert(row >= 0 && row < mod_matrix_slots); - modulation_entry &slot = mod_matrix[row]; - switch(column) { - case 0: - case 1: - { - for (int i = 0; monosynth_mod_src_names[i]; i++) - { - if (src == monosynth_mod_src_names[i]) - { - if (column == 0) - slot.src1 = i; - else - slot.src2 = i; - error.clear(); - return; - } - } - error = "Invalid source name"; - return; - } - case 2: - { - stringstream ss(src); - ss >> slot.amount; - error.clear(); - return; - } - case 3: - { - for (int i = 0; monosynth_mod_dest_names[i]; i++) - { - if (src == monosynth_mod_dest_names[i]) - { - slot.dest = i; - error.clear(); - return; - } - } - error = "Invalid destination name"; - return; - } - - } -} - -- 2.11.4.GIT