Merge branch 'calf-updates'

* calf-updates:
  Reimplement modulation matrix (and tables in general) using configure variables. Slow and most likely incomplete, but a good start.
  Add extra checks to detect when param_count != param array size - 1.
  Fix another install-related crash, this time due to invalid params in fluidsynth. (cherry picked from commit 034e3a47cd40eb6bb7d221274fda2a5c1c79f42f)
  Fix the infamous crash on install. (cherry picked from commit f0568e2f8a4c7d0003cc5a15e300aa2ebb3f93cb)
  The range given in the comment wasn't really correct. (cherry picked from commit 292cdaa81dab7e7d948f597041cb86d70dc5ff92)
  Use symmetric dB range for EQ plugins.
  Fix a few bugs in compilation of limited versions (DSSI without GUI, no JACK host).
  Initialise the vintage delay properly... hopefully this time. (cherry picked from commit c96ff1d680148cc877fab3b641d666068eea06aa)
  Unbreak Monosynth by changing listview to use a 'key' attribute instead of 'param'.
(cherry picked from commit c562952800)
This commit is contained in:
Tobias Doerffel
2010-12-05 23:10:48 +01:00
parent 20d6852cda
commit b1b63364d5
16 changed files with 1008 additions and 197 deletions

View File

@@ -222,27 +222,15 @@ struct table_column_info
};
/// 'has string parameters containing tabular data' interface
struct table_edit_iface
struct table_metadata_iface
{
/// retrieve the table layout for specific parameter
virtual const table_column_info *get_table_columns() const = 0;
/// return the current number of rows
/// return the fixed number of rows, or 0 if the number of rows is variable
virtual uint32_t get_table_rows() const = 0;
/// retrieve data item from the plugin
virtual std::string get_cell(int row, int column) const;
/// set data item to the plugin
virtual void set_cell(int row, int column, const std::string &src, std::string &error) { error.clear(); }
/// return a line graph interface for a specific parameter/column (unused for now)
virtual const line_graph_iface *get_graph_iface(int column) const { return NULL; }
/// return an editor name for a specific grid cell (unused for now - I don't even know how editors be implemented)
virtual const char *get_cell_editor(int column) const { return NULL; }
virtual ~table_edit_iface() {}
virtual ~table_metadata_iface() {}
};
/// 'may receive configure variables' interface
@@ -331,6 +319,8 @@ struct plugin_metadata_iface
virtual bool requires_configure() const = 0;
/// obtain array of names of configure variables (or NULL is none needed)
virtual const char *const *get_configure_vars() const { return NULL; }
/// @return table_metadata_iface if any
virtual const table_metadata_iface *get_table_metadata_iface(const char *key) const { return NULL; }
/// Do-nothing destructor to silence compiler warning
virtual ~plugin_metadata_iface() {}
@@ -365,8 +355,6 @@ struct plugin_ctl_iface
virtual const plugin_metadata_iface *get_metadata_iface() const = 0;
/// @return line_graph_iface if any
virtual const line_graph_iface *get_line_graph_iface() const = 0;
/// @return table_edit_iface if any
virtual table_edit_iface *get_table_edit_iface(const char *key) = 0;
/// Do-nothing destructor to silence compiler warning
virtual ~plugin_ctl_iface() {}
};
@@ -447,8 +435,6 @@ struct audio_module_iface
virtual uint32_t message_run(const void *valid_ports, void *output_ports) = 0;
/// @return line_graph_iface if any
virtual const line_graph_iface *get_line_graph_iface() const = 0;
/// @return table_edit_iface if any for given parameter
virtual table_edit_iface *get_table_edit_iface(const char *key) = 0;
virtual ~audio_module_iface() {}
};
@@ -548,8 +534,6 @@ public:
}
/// @return line_graph_iface if any
virtual const line_graph_iface *get_line_graph_iface() const { return dynamic_cast<const line_graph_iface *>(this); }
virtual table_edit_iface *get_table_edit_iface(const char *key) { const char *key_us = get_table_edit_iface_key(); return (key_us && !strcmp(key, key_us)) ? dynamic_cast<table_edit_iface *>(this) : NULL; }
virtual const char *get_table_edit_iface_key() const { return NULL; }
};
#if USE_EXEC_GUI || USE_DSSI
@@ -625,7 +609,7 @@ public:
};
#define CALF_PORT_NAMES(name) template<> const char *::plugin_metadata<name##_metadata>::port_names[]
#define CALF_PORT_PROPS(name) template<> parameter_properties plugin_metadata<name##_metadata>::param_props[]
#define CALF_PORT_PROPS(name) template<> parameter_properties plugin_metadata<name##_metadata>::param_props[name##_metadata::param_count + 1]
#define CALF_PLUGIN_INFO(name) template<> calf_plugins::ladspa_plugin_info plugin_metadata<name##_metadata>::plugin_info
#define PLUGIN_NAME_ID_LABEL(name, id, label) \
static const char *impl_get_name() { return name; } \
@@ -634,22 +618,22 @@ public:
extern const char *calf_copyright_info;
bool get_freq_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context, bool use_frequencies = true);
bool get_freq_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context, bool use_frequencies = true, float res = 256, float ofs = 0.4);
/// convert amplitude value to normalized grid-ish value (0dB = 0.5, 30dB = 1.0, -30 dB = 0.0, -60dB = -0.5, -90dB = -1.0)
static inline float dB_grid(float amp)
/// convert amplitude value to normalized grid-ish value
static inline float dB_grid(float amp, float res = 256, float ofs = 0.4)
{
return log(amp) * (1.0 / log(256.0)) + 0.4;
return log(amp) * (1.0 / log(res)) + ofs;
}
template<class Fx>
static bool get_graph(Fx &fx, int subindex, float *data, int points)
static bool get_graph(Fx &fx, int subindex, float *data, int points, float res = 256, float ofs = 0.4)
{
for (int i = 0; i < points; i++)
{
typedef std::complex<double> cfloat;
double freq = 20.0 * pow (20000.0 / 20.0, i * 1.0 / points);
data[i] = dB_grid(fx.freq_gain(subindex, freq, fx.srate));
data[i] = dB_grid(fx.freq_gain(subindex, freq, fx.srate), res, ofs);
}
return true;
}
@@ -678,8 +662,46 @@ struct preset_access_iface
virtual ~preset_access_iface() {}
};
/// Implementation of table_metadata_iface providing metadata for mod matrices
class mod_matrix_metadata: public table_metadata_iface
{
public:
/// Mapping modes
enum mapping_mode {
map_positive, ///< 0..100%
map_bipolar, ///< -100%..100%
map_negative, ///< -100%..0%
map_squared, ///< x^2
map_squared_bipolar, ///< x^2 scaled to -100%..100%
map_antisquared, ///< 1-(1-x)^2 scaled to 0..100%
map_antisquared_bipolar, ///< 1-(1-x)^2 scaled to -100..100%
map_parabola, ///< inverted parabola (peaks at 0.5, then decreases to 0)
map_type_count
};
const char **mod_src_names, **mod_dest_names;
mod_matrix_metadata(unsigned int _rows, const char **_src_names, const char **_dest_names);
virtual const table_column_info *get_table_columns() const;
virtual uint32_t get_table_rows() const;
protected:
/// Column descriptions for table widget
table_column_info table_columns[6];
unsigned int matrix_rows;
};
/// Check if a given key is either prefix + rows or prefix + i2s(row) + "," + i2s(column)
/// @arg key key to parse
/// @arg prefix table prefix (e.g. "modmatrix:")
/// @arg is_rows[out] set to true if key == prefix + "rows"
/// @arg row[out] if key is of a form: prefix + row + "," + i2s(column), returns row, otherwise returns -1
/// @arg column[out] if key is of a form: prefix + row + "," + i2s(column), returns row, otherwise returns -1
/// @retval true if this is one of the recognized string forms
extern bool parse_table_key(const char *key, const char *prefix, bool &is_rows, int &row, int &column);
#if USE_EXEC_GUI
class table_via_configure: public table_edit_iface
class table_via_configure
{
protected:
typedef std::pair<int, int> coord;
@@ -689,13 +711,6 @@ protected:
public:
table_via_configure();
void configure(const char *key, const char *value);
virtual const table_column_info *get_table_columns() const;
virtual uint32_t get_table_rows() const;
virtual std::string get_cell(int row, int column) const;
virtual void set_cell(int row, int column, const std::string &src, std::string &error);
virtual const line_graph_iface *get_graph_iface(int column) const;
virtual const char *get_cell_editor(int column) const;
virtual ~table_via_configure();
};
#endif

View File

@@ -48,7 +48,6 @@ struct ladspa_instance: public plugin_ctl_iface
ladspa_instance(audio_module_iface *_module, ladspa_plugin_metadata_set *_ladspa, int sample_rate);
virtual const line_graph_iface *get_line_graph_iface() const { return module->get_line_graph_iface(); }
virtual table_edit_iface *get_table_edit_iface(const char *key) { return module->get_table_edit_iface(key); }
virtual float get_param_value(int param_no);
virtual void set_param_value(int param_no, float value);
virtual bool activate_preset(int bank, int program);

View File

@@ -28,7 +28,7 @@
#include <lv2.h>
#include <calf/giface.h>
#include <calf/lv2_event.h>
#include <calf/lv2_persist.h>
#include <calf/lv2_persist2.h>
#include <calf/lv2_progress.h>
#include <calf/lv2_uri_map.h>
#include <string.h>
@@ -91,11 +91,15 @@ struct lv2_instance: public plugin_ctl_iface, public progress_report_iface
const char *const *vars = module->get_metadata_iface()->get_configure_vars();
if (!vars)
return;
assert(uri_map);
uint32_t string_type = uri_map->uri_to_id(uri_map, NULL, "http://lv2plug.in/ns/ext/atom#String");
assert(string_type);
for (unsigned int i = 0; vars[i]; i++)
{
size_t len = 0;
const void *ptr = (*retrieve)(callback_data, vars[i], &len);
if (ptr)
uint32_t type = 0;
const void *ptr = (*retrieve)(callback_data, vars[i], &len, &type);
if (ptr && type == string_type)
{
printf("Calling configure on %s\n", vars[i]);
configure(vars[i], std::string((const char *)ptr, len).c_str());
@@ -160,7 +164,6 @@ struct lv2_instance: public plugin_ctl_iface, public progress_report_iface
}
virtual const plugin_metadata_iface *get_metadata_iface() const { return metadata; }
virtual const line_graph_iface *get_line_graph_iface() const { return module->get_line_graph_iface(); }
virtual table_edit_iface *get_table_edit_iface(const char *key) { return module->get_table_edit_iface(key); }
virtual int send_status_updates(send_updates_iface *sui, int last_serial) { return module->send_status_updates(sui, last_serial); }
};
@@ -297,15 +300,20 @@ struct lv2_wrapper
{
LV2_Persist_Store_Function store;
void *callback_data;
uint32_t string_data_type;
virtual void send_configure(const char *key, const char *value)
{
(*store)(callback_data, key, value, strlen(value));
(*store)(callback_data, key, value, strlen(value) + 1, string_data_type);
}
};
// A host that supports a Persist extension should support an URI map extension as well.
assert(inst->uri_map);
store_state s;
s.store = store;
s.callback_data = callback_data;
s.string_data_type = inst->uri_map->uri_to_id(inst->uri_map, NULL, "http://lv2plug.in/ns/ext/atom#String");
inst->send_configures(&s);
}
static void cb_persist_restore(LV2_Handle Instance, LV2_Persist_Retrieve_Function retrieve, void *callback_data)

View File

@@ -118,6 +118,7 @@ struct monosynth_metadata: public plugin_metadata<monosynth_metadata>
param_count };
enum { in_count = 0, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = true, rt_capable = true };
enum { step_size = 64, step_shift = 6 };
enum { mod_matrix_slots = 10 };
enum {
modsrc_none,
modsrc_velocity,
@@ -143,6 +144,12 @@ struct monosynth_metadata: public plugin_metadata<monosynth_metadata>
moddest_count,
};
PLUGIN_NAME_ID_LABEL("monosynth", "monosynth", "Monosynth")
mod_matrix_metadata mm_metadata;
monosynth_metadata();
/// Lookup of table edit interface
virtual const table_metadata_iface *get_table_metadata_iface(const char *key) const { if (!strcmp(key, "mod_matrix")) return &mm_metadata; else return NULL; }
};
/// Thor's compressor - metadata
@@ -348,12 +355,8 @@ struct organ_enums
par_bassgain,
par_treblefreq,
par_treblegain,
par_var_mapcurve,
param_count
};
enum {
var_count = 1
};
enum organ_waveform {
wave_sine,
wave_sinepl1, wave_sinepl2, wave_sinepl3,
@@ -412,7 +415,7 @@ public:
/// FluidSynth - metadata
struct fluidsynth_metadata: public plugin_metadata<fluidsynth_metadata>
{
enum { par_master, par_interpolation, par_reverb, par_chorus, par_soundfont, par_preset_key_set, param_count };
enum { par_master, par_interpolation, par_reverb, par_chorus, param_count };
enum { in_count = 0, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = true, rt_capable = false };
PLUGIN_NAME_ID_LABEL("fluidsynth", "fluidsynth", "Fluidsynth")
@@ -486,8 +489,14 @@ struct wavetable_metadata: public plugin_metadata<wavetable_metadata>
par_pwhlrange,
param_count };
enum { in_count = 0, out_count = 2, ins_optional = 0, outs_optional = 0, support_midi = true, require_midi = true, rt_capable = true };
enum { mod_matrix_slots = 10 };
enum { step_size = 64 };
PLUGIN_NAME_ID_LABEL("wavetable", "wavetable", "Wavetable")
mod_matrix_metadata mm_metadata;
wavetable_metadata();
/// Lookup of table edit interface
virtual const table_metadata_iface *get_table_metadata_iface(const char *key) const { if (!strcmp(key, "mod_matrix")) return &mm_metadata; else return NULL; }
};
};

View File

@@ -25,26 +25,13 @@
namespace dsp {
/// Mapping modes
enum mapping_mode {
map_positive, ///< 0..100%
map_bipolar, ///< -100%..100%
map_negative, ///< -100%..0%
map_squared, ///< x^2
map_squared_bipolar, ///< x^2 scaled to -100%..100%
map_antisquared, ///< 1-(1-x)^2 scaled to 0..100%
map_antisquared_bipolar, ///< 1-(1-x)^2 scaled to -100..100%
map_parabola, ///< inverted parabola (peaks at 0.5, then decreases to 0)
map_type_count
};
/// Single entry in modulation matrix
struct modulation_entry
{
/// Mapped source
int src1;
/// Source mapping mode
mapping_mode mapping;
calf_plugins::mod_matrix_metadata::mapping_mode mapping;
/// Unmapped modulating source
int src2;
/// Modulation amount
@@ -60,7 +47,7 @@ struct modulation_entry
void reset() {
src1 = 0;
src2 = 0;
mapping = map_positive;
mapping = calf_plugins::mod_matrix_metadata::map_positive;
amount = 0.f;
dest = 0;
}
@@ -70,24 +57,17 @@ struct modulation_entry
namespace calf_plugins {
class mod_matrix: public table_edit_iface
class mod_matrix_impl
{
protected:
/// Polynomials for different scaling modes (1, x, x^2)
static const float scaling_coeffs[dsp::map_type_count][3];
/// Column descriptions for table widget
table_column_info table_columns[6];
dsp::modulation_entry *matrix;
mod_matrix_metadata *metadata;
unsigned int matrix_rows;
const char **mod_src_names, **mod_dest_names;
/// Polynomials for different scaling modes (1, x, x^2)
static const float scaling_coeffs[calf_plugins::mod_matrix_metadata::map_type_count][3];
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() const;
virtual uint32_t get_table_rows() const;
virtual std::string get_cell(int row, int column) const;
virtual void set_cell(int row, int column, const std::string &src, std::string &error);
mod_matrix_impl(dsp::modulation_entry *_matrix, calf_plugins::mod_matrix_metadata *_metadata);
/// Process modulation matrix, calculate outputs from inputs
inline void calculate_modmatrix(float *moddest, int moddest_count, float *modsrc)
@@ -105,8 +85,14 @@ public:
}
}
}
};
void send_configures(send_configure_iface *);
char *configure(const char *key, const char *value);
private:
std::string get_cell(int row, int column) const;
void set_cell(int row, int column, const std::string &src, std::string &error);
};
};
#endif

View File

@@ -37,10 +37,9 @@ namespace calf_plugins {
/// 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<monosynth_metadata>, public line_graph_iface, public mod_matrix
class monosynth_audio_module: public audio_module<monosynth_metadata>, public line_graph_iface, public mod_matrix_impl
{
public:
enum { mod_matrix_slots = 10 };
uint32_t srate, crate;
static dsp::waveform_family<MONOSYNTH_WAVE_BITS> *waves;
dsp::waveform_oscillator<MONOSYNTH_WAVE_BITS> osc1, osc2;
@@ -178,6 +177,9 @@ public:
void apply_fadeout();
/// Main processing function
uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask);
/// Send all configure variables set within a plugin to given destination (which may be limited to only those that plugin understands)
virtual void send_configures(send_configure_iface *sci) { return mod_matrix_impl::send_configures(sci); }
virtual char *configure(const char *key, const char *value) { return mod_matrix_impl::configure(key, value); }
};
};

View File

@@ -0,0 +1,164 @@
#ifndef __CALF_WAVETABLE_H
#define __CALF_WAVETABLE_H
#include <assert.h>
#include "biquad.h"
#include "onepole.h"
#include "audio_fx.h"
#include "inertia.h"
#include "osc.h"
#include "synth.h"
#include "envelope.h"
#include "modmatrix.h"
namespace calf_plugins {
#define WAVETABLE_WAVE_BITS 8
class wavetable_audio_module;
struct wavetable_oscillator: public dsp::simple_oscillator
{
enum { SIZE = 1 << 8, MASK = SIZE - 1, SCALE = 1 << (32 - 8) };
int16_t (*tables)[256];
inline float get(uint16_t slice)
{
float fracslice = (slice & 255) * (1.0 / 256.0);
slice = slice >> 8;
int16_t *waveform = tables[slice];
int16_t *waveform2 = tables[slice + 1];
float value1 = 0.f, value2 = 0.f;
uint32_t cphase = phase, cphasedelta = phasedelta >> 3;
for (int j = 0; j < 8; j++)
{
uint32_t wpos = cphase >> (32 - 8);
uint32_t wpos2 = (wpos + 1) & MASK;
float frac = (cphase & (SCALE - 1)) * (1.0f / SCALE);
value1 += dsp::lerp((float)waveform[wpos], (float)waveform[wpos2], frac);
value2 += dsp::lerp((float)waveform2[wpos], (float)waveform2[wpos2], frac);
cphase += cphasedelta;
}
phase += phasedelta;
return dsp::lerp(value1, value2, fracslice) * (1.0 / 8.0) * (1.0 / 32768.0);;
}
};
class wavetable_voice: public dsp::voice
{
public:
enum { Channels = 2, BlockSize = 64, EnvCount = 3, OscCount = 2 };
float output_buffer[BlockSize][Channels];
protected:
int note;
wavetable_audio_module *parent;
float **params;
dsp::decay amp;
wavetable_oscillator oscs[OscCount];
dsp::adsr envs[EnvCount];
/// Current MIDI velocity
float velocity;
/// Current calculated mod matrix outputs
float moddest[wavetable_metadata::moddest_count];
/// Last oscillator shift (wavetable index) of each oscillator
float last_oscshift[OscCount];
/// Last oscillator amplitude of each oscillator
float last_oscamp[OscCount];
/// Current osc amplitude
float cur_oscamp[OscCount];
public:
wavetable_voice();
void set_params_ptr(wavetable_audio_module *_parent, int _srate);
void reset();
void note_on(int note, int vel);
void note_off(int /* vel */);
void channel_pressure(int value);
void steal();
void render_block();
virtual int get_current_note() {
return note;
}
virtual bool get_active() {
// printf("note %d getactive %d use_percussion %d pamp active %d\n", note, amp.get_active(), use_percussion(), pamp.get_active());
return (note != -1) && (amp.get_active()) && !envs[0].stopped();
}
inline void calc_derived_dests() {
float cv = dsp::clip<float>(0.5f + moddest[wavetable_metadata::moddest_oscmix], 0.f, 1.f);
cur_oscamp[0] = (cv) * *params[wavetable_metadata::par_o1level];
cur_oscamp[1] = (1 - cv) * *params[wavetable_metadata::par_o2level];
}
};
class wavetable_audio_module: public audio_module<wavetable_metadata>, public dsp::basic_synth, public mod_matrix_impl
{
public:
using dsp::basic_synth::note_on;
using dsp::basic_synth::note_off;
using dsp::basic_synth::control_change;
using dsp::basic_synth::pitch_bend;
protected:
uint32_t crate;
bool panic_flag;
public:
int16_t tables[wt_count][129][256]; // one dummy level for interpolation
/// Rows of the modulation matrix
dsp::modulation_entry mod_matrix_data[mod_matrix_slots];
/// Smoothed cutoff value
dsp::inertia<dsp::exponential_ramp> inertia_cutoff;
/// Smoothed pitch bend value
dsp::inertia<dsp::exponential_ramp> inertia_pitchbend;
/// Smoothed channel pressure value
dsp::inertia<dsp::linear_ramp> inertia_pressure;
/// Unsmoothed mod wheel value
float modwheel_value;
public:
wavetable_audio_module();
dsp::voice *alloc_voice() {
dsp::block_voice<wavetable_voice> *v = new dsp::block_voice<wavetable_voice>();
v->set_params_ptr(this, sample_rate);
return v;
}
/// process function copied from Organ (will probably need some adjustments as well as implementing the panic flag elsewhere
uint32_t process(uint32_t offset, uint32_t nsamples, uint32_t inputs_mask, uint32_t outputs_mask) {
float *o[2] = { outs[0] + offset, outs[1] + offset };
if (panic_flag)
{
control_change(120, 0); // stop all sounds
control_change(121, 0); // reset all controllers
panic_flag = false;
}
float buf[4096][2];
dsp::zero(&buf[0][0], 2 * nsamples);
basic_synth::render_to(buf, nsamples);
float gain = 1.0f;
for (uint32_t i=0; i<nsamples; i++) {
o[0][i] = gain*buf[i][0];
o[1][i] = gain*buf[i][1];
}
return 3;
}
void set_sample_rate(uint32_t sr) {
setup(sr);
crate = sample_rate / wavetable_voice::BlockSize;
inertia_cutoff.ramp.set_length(crate / 30); // 1/30s
inertia_pitchbend.ramp.set_length(crate / 30); // 1/30s
inertia_pressure.ramp.set_length(crate / 30); // 1/30s - XXXKF monosynth needs that too
}
/// Handle MIDI Channel Pressure
void channel_pressure(int value);
/// Handle pitch bend message.
inline void pitch_bend(int value)
{
inertia_pitchbend.set_inertia(pow(2.0, (value * *params[par_pwhlrange]) / (1200.0 * 8192.0)));
}
};
};
#endif

View File

@@ -214,7 +214,7 @@ const char *calf_plugins::load_gui_xml(const std::string &plugin_id)
}
}
bool calf_plugins::get_freq_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context, bool use_frequencies)
bool calf_plugins::get_freq_gridline(int subindex, float &pos, bool &vertical, std::string &legend, cairo_iface *context, bool use_frequencies, float res, float ofs)
{
if (subindex < 0 )
return false;
@@ -247,7 +247,7 @@ bool calf_plugins::get_freq_gridline(int subindex, float &pos, bool &vertical, s
if (subindex >= 32)
return false;
float gain = 16.0 / (1 << subindex);
pos = dB_grid(gain);
pos = dB_grid(gain, res, ofs);
if (pos < -1)
return false;
if (subindex != 4)
@@ -319,11 +319,67 @@ const plugin_metadata_iface *calf_plugins::plugin_registry::get_by_id(const char
}
return NULL;
}
///////////////////////////////////////////////////////////////////////////////////////
std::string table_edit_iface::get_cell(int row, int column) const
bool calf_plugins::parse_table_key(const char *key, const char *prefix, bool &is_rows, int &row, int &column)
{
return calf_utils::i2s(row)+":"+calf_utils::i2s(column);
is_rows = false;
row = -1;
column = -1;
if (0 != strncmp(key, prefix, strlen(prefix)))
return false;
key += strlen(prefix);
if (!strcmp(key, "rows"))
{
is_rows = true;
return true;
}
const char *comma = strchr(key, ',');
if (comma)
{
row = atoi(string(key, comma - key).c_str());
column = atoi(comma + 1);
return true;
}
printf("Unknown key %s under prefix %s", key, prefix);
return false;
}
///////////////////////////////////////////////////////////////////////////////////////
const char *mod_mapping_names[] = { "0..1", "-1..1", "-1..0", "x^2", "2x^2-1", "ASqr", "ASqrBip", "Para", NULL };
mod_matrix_metadata::mod_matrix_metadata(unsigned int _rows, const char **_src_names, const char **_dest_names)
: mod_src_names(_src_names)
, mod_dest_names(_dest_names)
, matrix_rows(_rows)
{
table_column_info tci[6] = {
{ "Source", TCT_ENUM, 0, 0, 0, mod_src_names },
{ "Mapping", TCT_ENUM, 0, 0, 0, mod_mapping_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_metadata::get_table_columns() const
{
return table_columns;
}
uint32_t mod_matrix_metadata::get_table_rows() const
{
return matrix_rows;
}
///////////////////////////////////////////////////////////////////////////////////////
@@ -435,45 +491,6 @@ table_via_configure::table_via_configure()
rows = 0;
}
const table_column_info *table_via_configure::get_table_columns() const
{
return &columns[0];
}
uint32_t table_via_configure::get_table_rows() const
{
return rows;
}
string table_via_configure::get_cell(int row, int column) const
{
if (row >= rows)
return string();
coord c = make_pair(row, column);
std::map<coord, std::string>::const_iterator i = values.find(c);
if (i == values.end())
return std::string();
else
return i->second;
}
void table_via_configure::set_cell(int row, int column, const std::string &src, std::string &error)
{
coord c = make_pair(row, column);
values[c] = src;
error = "";
}
const line_graph_iface *table_via_configure::get_graph_iface(int column) const
{
return NULL;
}
const char *table_via_configure::get_cell_editor(int column) const
{
return NULL;
}
table_via_configure::~table_via_configure()
{
}

View File

@@ -41,6 +41,7 @@ CALF_PORT_PROPS(flanger) = {
{ 0, 0, 1, 2, PF_BOOL | PF_CTL_BUTTON , NULL, "reset", "Reset" },
{ 1, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "amount", "Amount" },
{ 1.0, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" },
{}
};
CALF_PLUGIN_INFO(flanger) = { 0x847d, "Flanger", "Calf Flanger", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "FlangerPlugin" };
@@ -82,6 +83,7 @@ CALF_PORT_PROPS(reverb) = {
{ 0, 0, 50, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "predelay", "Pre Delay" },
{ 300, 20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "bass_cut", "Bass Cut" },
{ 5000, 20, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "treble_cut", "Treble Cut" },
{}
};
CALF_PLUGIN_INFO(reverb) = { 0x847e, "Reverb", "Calf Reverb", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "ReverbPlugin" };
@@ -129,7 +131,8 @@ CALF_PORT_PROPS(filterclavier) = {
biquad_filter_module::mode_12db_lp,
biquad_filter_module::mode_count - 1,
1, PF_ENUM | PF_CTL_COMBO | PF_PROP_GRAPH, filter_choices, "mode", "Mode" },
{ 20, 1, 2000, 20, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "inertia", "Portamento time"}
{ 20, 1, 2000, 20, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "inertia", "Portamento time"},
{}
};
CALF_PLUGIN_INFO(filterclavier) = { 0x849f, "Filterclavier", "Calf Filterclavier", "Krzysztof Foltman / Hans Baier", calf_plugins::calf_copyright_info, "FilterclavierPlugin" };
@@ -162,6 +165,7 @@ CALF_PORT_PROPS(vintage_delay) = {
{ 1, 0, 2, 0, PF_ENUM | PF_CTL_COMBO, vintage_delay_fbmodes, "medium", "Medium" },
{ 1.0, 0, 4, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_COEF | PF_PROP_NOBOUNDS, NULL, "dry", "Dry Amount" },
{ 1.0, -1, 1, 0, PF_FLOAT | PF_SCALE_PERC | PF_CTL_KNOB , NULL, "width", "Stereo Width" },
{}
};
CALF_PLUGIN_INFO(vintage_delay) = { 0x8482, "VintageDelay", "Calf Vintage Delay", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "DelayPlugin" };
@@ -183,6 +187,7 @@ CALF_PORT_PROPS(rotary_speaker) = {
{ 0.3, 0, 1, 101, PF_FLOAT | PF_CTL_KNOB | PF_SCALE_PERC, NULL, "reflection", "Reflection" },
{ 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_l", "Low rotor" },
{ 0, 0, 1, 0, PF_FLOAT | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "meter_h", "High rotor" },
{}
};
CALF_PLUGIN_INFO(rotary_speaker) = { 0x8483, "RotarySpeaker", "Calf Rotary Speaker", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "SimulatorPlugin" };
@@ -231,6 +236,7 @@ CALF_PORT_PROPS(compressor) = {
{ 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, compressor_detection_names, "detection", "Detection" },
{ 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, compressor_stereo_link_names, "stereo_link", "Stereo Link" },
{ 0, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "compression", "Reduction" },
{}
};
CALF_PLUGIN_INFO(compressor) = { 0x8502, "Compressor", "Calf Compressor", "Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" };
@@ -278,6 +284,7 @@ CALF_PORT_PROPS(sidechaincompressor) = {
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "sc_listen", "S/C-Listen" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "f1_active", "F1 Active" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "f2_active", "F2 Active" },
{}
};
CALF_PLUGIN_INFO(sidechaincompressor) = { 0x8517, "Sidechaincompressor", "Calf Sidechain Compressor", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" };
@@ -364,6 +371,7 @@ CALF_PORT_PROPS(multibandcompressor) = {
{ 0, 0, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "output3", "Output 4" },
{ 1, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "bypass3", "Bypass 4" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mute3", "Mute 4" },
{}
};
CALF_PLUGIN_INFO(multibandcompressor) = { 0x8516, "Multibandcompressor", "Calf Multiband Compressor", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" };
@@ -395,6 +403,7 @@ CALF_PORT_PROPS(deesser) = {
{ 4, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "f2_level", "Level" },
{ 1, 0.1, 100,1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "f2_q", "Peak Q" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "sc_listen", "S/C-Listen" },
{}
};
CALF_PLUGIN_INFO(deesser) = { 0x8515, "Deesser", "Calf Deesser", "Markus Schmidt / Thor Harald Johansen", calf_plugins::calf_copyright_info, "CompressorPlugin" };
@@ -423,6 +432,7 @@ CALF_PORT_PROPS(gate) = {
{ 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, gate_detection_names, "detection", "Detection" },
{ 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, gate_stereo_link_names, "stereo_link", "Stereo Link" },
{ 0, 0.03125, 1, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_METER | PF_CTLO_LABEL | PF_CTLO_REVERSE | PF_UNIT_DB | PF_PROP_OUTPUT | PF_PROP_OPTIONAL| PF_PROP_GRAPH, NULL, "gating", "Gating" },
{}
};
CALF_PLUGIN_INFO(gate) = { 0x8503, "Gate", "Calf Gate", "Damien Zammit / Thor Harald Johansen", calf_plugins::calf_copyright_info, "ExpanderPlugin" };
@@ -471,6 +481,7 @@ CALF_PORT_PROPS(sidechaingate) = {
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "sc_listen", "S/C-Listen" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "f1_active", "F1 Active" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_LED | PF_PROP_OUTPUT | PF_PROP_OPTIONAL, NULL, "f2_active", "F2 Active" },
{}
};
CALF_PLUGIN_INFO(sidechaingate) = { 0x8504, "Sidechaingate", "Calf Sidechain Gate", "Markus Schmidt / Damien Zammit / Thor Harald Johansen", calf_plugins::calf_copyright_info, "ExpanderPlugin" };
@@ -527,6 +538,7 @@ CALF_PORT_PROPS(equalizer5band) = {
EQ_BAND_PARAMS(1, 250)
EQ_BAND_PARAMS(2, 1000)
EQ_BAND_PARAMS(3, 2500)
{}
};
CALF_PLUGIN_INFO(equalizer5band) = { 0x8511, "Equalizer5Band", "Calf Equalizer 5 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" };
@@ -546,6 +558,7 @@ CALF_PORT_PROPS(equalizer8band) = {
EQ_BAND_PARAMS(2, 1000)
EQ_BAND_PARAMS(3, 2500)
EQ_BAND_PARAMS(4, 5000)
{}
};
CALF_PLUGIN_INFO(equalizer8band) = { 0x8512, "Equalizer8Band", "Calf Equalizer 8 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" };
@@ -567,6 +580,7 @@ CALF_PORT_PROPS(equalizer12band) = {
EQ_BAND_PARAMS(6, 2500)
EQ_BAND_PARAMS(7, 4000)
EQ_BAND_PARAMS(8, 6000)
{}
};
CALF_PLUGIN_INFO(equalizer12band) = { 0x8513, "Equalizer12Band", "Calf Equalizer 12 Band", "Markus Schmidt", calf_plugins::calf_copyright_info, "EqualizerPlugin" };
@@ -586,6 +600,7 @@ CALF_PORT_PROPS(pulsator) = {
{ 0.5, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "offset", "Offset L/R" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "mono", "Mono-in" },
{ 0, 0, 1, 2, PF_BOOL | PF_CTL_BUTTON , NULL, "reset", "Reset" },
{}
};
CALF_PLUGIN_INFO(pulsator) = { 0x8514, "Pulsator", "Calf Pulsator", "Markus Schmidt", calf_plugins::calf_copyright_info, "ModulationPlugin" };
@@ -617,6 +632,7 @@ CALF_PORT_PROPS(saturator) = {
{ 2000, 80, 8000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "p_freq", "Tone" },
{ 1, 0.0625, 16, 0, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB | PF_UNIT_DB, NULL, "p_level", "Amount" },
{ 1, 0.1, 10, 1, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_COEF, NULL, "p_q", "Gradient" },
{}
};
CALF_PLUGIN_INFO(saturator) = { 0x8530, "Saturator", "Calf Saturator", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" };
@@ -641,6 +657,7 @@ CALF_PORT_PROPS(exciter) = {
{ 6000, 2000, 12000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "freq", "Scope" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "listen", "Listen" },
{}
};
CALF_PLUGIN_INFO(exciter) = { 0x8531, "Exciter", "Calf Exciter", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" };
@@ -665,6 +682,7 @@ CALF_PORT_PROPS(bassenhancer) = {
{ 120, 10, 250, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "freq", "Scope" },
{ 0, 0, 1, 0, PF_BOOL | PF_CTL_TOGGLE, NULL, "listen", "Listen" },
{}
};
CALF_PLUGIN_INFO(bassenhancer) = { 0x8532, "BassEnhancer", "Calf Bass Enhancer", "Markus Schmidt / Krzysztof Foltman", calf_plugins::calf_copyright_info, "DistortionPlugin" };
@@ -756,8 +774,40 @@ CALF_PORT_PROPS(monosynth) = {
{ 0, 0, 1, 0, PF_ENUM | PF_CTL_COMBO, monosynth_lfotrig_names, "lfo2_trig", "LFO2 Trigger Mode" },
{ 5, 0.01, 20, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_HZ, NULL, "lfo2_rate", "LFO1 Rate" },
{ 0.5, 0.1, 5, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_SEC, NULL, "lfo2_delay", "LFO1 Delay" },
{}
};
static const char *monosynth_mod_src_names[] = {
"None",
"Velocity",
"Pressure",
"ModWheel",
"Envelope 1",
"Envelope 2",
"LFO 1",
"LFO 2",
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 (%)",
"O1: Stretch",
NULL
};
monosynth_metadata::monosynth_metadata()
: mm_metadata(mod_matrix_slots, monosynth_mod_src_names, monosynth_mod_dest_names)
{
}
////////////////////////////////////////////////////////////////////////////
CALF_PLUGIN_INFO(organ) = { 0x8481, "Organ", "Calf Organ", "Krzysztof Foltman", calf_plugins::calf_copyright_info, "SynthesizerPlugin" };
@@ -1018,7 +1068,29 @@ const char *wavetable_names[] = {
"Multi 2",
};
const char *wavetable_init_soundfont = "";
static const char *wavetable_mod_src_names[] = {
"None",
"Velocity",
"Pressure",
"ModWheel",
"Env 1",
"Env 2",
"Env 3",
NULL
};
static const char *wavetable_mod_dest_names[] = {
"None",
"Attenuation",
"Osc Mix Ratio (%)",
"Cutoff [ct]",
"Resonance",
"O1: Shift (%)",
"O2: Shift (%)",
"O1: Detune [ct]",
"O2: Detune [ct]",
NULL
};
CALF_PORT_NAMES(wavetable) = {
"Out L", "Out R",
@@ -1061,8 +1133,14 @@ CALF_PORT_PROPS(wavetable) = {
{ 0, 0, 1, 0, PF_FLOAT | PF_SCALE_PERC, NULL, "adsr3_v", "EG3 VelMod" },
{ 200, 0, 2400, 25, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_KNOB | PF_UNIT_CENTS, NULL, "pbend_range", "PBend Range" },
{}
};
wavetable_metadata::wavetable_metadata()
: mm_metadata(mod_matrix_slots, wavetable_mod_src_names, wavetable_mod_dest_names)
{
}
////////////////////////////////////////////////////////////////////////////
calf_plugins::plugin_registry::plugin_registry()

View File

@@ -26,10 +26,18 @@
using namespace std;
using namespace dsp;
using namespace calf_plugins;
using namespace calf_utils;
const char *mod_mapping_names[] = { "0..1", "-1..1", "-1..0", "x^2", "2x^2-1", "ASqr", "ASqrBip", "Para", NULL };
mod_matrix_impl::mod_matrix_impl(dsp::modulation_entry *_matrix, mod_matrix_metadata *_metadata)
: matrix(_matrix)
, metadata(_metadata)
{
matrix_rows = metadata->get_table_rows();
for (unsigned int i = 0; i < matrix_rows; i++)
matrix[i].reset();
}
const float mod_matrix::scaling_coeffs[dsp::map_type_count][3] = {
const float mod_matrix_impl::scaling_coeffs[mod_matrix_metadata::map_type_count][3] = {
{ 0, 1, 0 },
{ -1, 2, 0 },
{ -1, 1, 0 },
@@ -40,66 +48,33 @@ const float mod_matrix::scaling_coeffs[dsp::map_type_count][3] = {
{ 0, 4, -4 },
};
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[6] = {
{ "Source", TCT_ENUM, 0, 0, 0, mod_src_names },
{ "Mapping", TCT_ENUM, 0, 0, 0, mod_mapping_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));
for (unsigned int i = 0; i < matrix_rows; i++)
matrix[i].reset();
}
const table_column_info *mod_matrix::get_table_columns() const
{
return table_columns;
}
uint32_t mod_matrix::get_table_rows() const
{
return matrix_rows;
}
std::string mod_matrix::get_cell(int row, int column) const
std::string mod_matrix_impl::get_cell(int row, int column) const
{
assert(row >= 0 && row < (int)matrix_rows);
modulation_entry &slot = matrix[row];
const char **arr = metadata->get_table_columns()[column].values;
switch(column) {
case 0: // source 1
return mod_src_names[slot.src1];
return arr[slot.src1];
case 1: // mapping mode
return mod_mapping_names[slot.mapping];
return arr[slot.mapping];
case 2: // source 2
return mod_src_names[slot.src2];
return arr[slot.src2];
case 3: // amount
return calf_utils::f2s(slot.amount);
case 4: // destination
return mod_dest_names[slot.dest];
return arr[slot.dest];
default:
assert(0);
return "";
}
}
void mod_matrix::set_cell(int row, int column, const std::string &src, std::string &error)
void mod_matrix_impl::set_cell(int row, int column, const std::string &src, std::string &error)
{
assert(row >= 0 && row < (int)matrix_rows);
modulation_entry &slot = matrix[row];
const char **arr = mod_src_names;
if (column == 1)
arr = mod_mapping_names;
if (column == 4)
arr = mod_dest_names;
const char **arr = metadata->get_table_columns()[column].values;
switch(column) {
case 0:
case 1:
@@ -113,7 +88,7 @@ void mod_matrix::set_cell(int row, int column, const std::string &src, std::stri
if (column == 0)
slot.src1 = i;
else if (column == 1)
slot.mapping = (mapping_mode)i;
slot.mapping = (mod_matrix_metadata::mapping_mode)i;
else if (column == 2)
slot.src2 = i;
else if (column == 4)
@@ -135,3 +110,33 @@ void mod_matrix::set_cell(int row, int column, const std::string &src, std::stri
}
}
void mod_matrix_impl::send_configures(send_configure_iface *sci)
{
for (int i = 0; i < (int)matrix_rows; i++)
{
for (int j = 0; j < 5; j++)
{
string key = "mod_matrix:" + i2s(i) + "," + i2s(j);
sci->send_configure(key.c_str(), get_cell(i, j).c_str());
}
}
}
char *mod_matrix_impl::configure(const char *key, const char *value)
{
bool is_rows;
int row, column;
if (!parse_table_key(key, "mod_matrix:", is_rows, row, column))
return NULL;
if (is_rows)
return strdup("Unexpected key");
if (row != -1 && column != -1)
{
string error;
set_cell(row, column, value, error);
if (!error.empty())
return strdup(error.c_str());
}
return NULL;
}

View File

@@ -189,6 +189,7 @@ static inline void delayline_impl(int age, int deltime, float dry_value, const f
// if the buffer hasn't been cleared yet (after activation), pretend we've read zeros
if (age <= deltime) {
out = 0;
del = dry_value;
amt.step();
fb.step();
}
@@ -206,6 +207,7 @@ static inline void delayline2_impl(int age, int deltime, float dry_value, const
{
if (age <= deltime) {
out = 0;
del = dry_value;
amt.step();
fb.step();
}

View File

@@ -248,7 +248,7 @@ bool equalizerNband_audio_module<BaseClass, has_lphp>::get_graph(int index, int
return false;
if (index == AM::param_p1_freq && !subindex) {
context->set_line_width(1.5);
return ::get_graph(*this, subindex, data, points);
return ::get_graph(*this, subindex, data, points, 32, 0);
}
return false;
}
@@ -259,7 +259,7 @@ bool equalizerNband_audio_module<BaseClass, has_lphp>::get_gridline(int index, i
if (!is_active) {
return false;
} else {
return get_freq_gridline(subindex, pos, vertical, legend, context);
return get_freq_gridline(subindex, pos, vertical, legend, context, true, 32, 0);
}
}

View File

@@ -27,34 +27,8 @@ using namespace std;
float silence[4097];
static const char *monosynth_mod_src_names[] = {
"None",
"Velocity",
"Pressure",
"ModWheel",
"Envelope 1",
"Envelope 2",
"LFO 1",
"LFO 2",
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 (%)",
"O1: Stretch",
NULL
};
monosynth_audio_module::monosynth_audio_module()
: mod_matrix(mod_matrix_data, mod_matrix_slots, monosynth_mod_src_names, monosynth_mod_dest_names)
: mod_matrix_impl(mod_matrix_data, &mm_metadata)
, inertia_cutoff(1)
, inertia_pitchbend(1)
, inertia_pressure(64)

View File

@@ -62,7 +62,7 @@ uint32_t organ_audio_module::process(uint32_t offset, uint32_t nsamples, uint32_
}
void organ_audio_module::params_changed() {
for (int i = 0; i < param_count - var_count; i++)
for (int i = 0; i < param_count; i++)
((float *)&par_values)[i] = *params[i];
unsigned int old_poly = polyphony_limit;

View File

@@ -116,7 +116,7 @@ void ladspa_instance::run_synth(unsigned long SampleCount, snd_seq_event_t *Even
char *ladspa_instance::configure(const char *key, const char *value)
{
#if USE_DSSI
#if USE_DSSI_GUI
if (!strcmp(key, "OSC:FEEDBACK_URI"))
{
const line_graph_iface *lgi = dynamic_cast<const line_graph_iface *>(metadata);

View File

@@ -0,0 +1,552 @@
/* Calf DSP Library
* Example audio modules - wavetable synthesizer
*
* 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 02110-1301 USA
*/
#include <config.h>
#if ENABLE_EXPERIMENTAL
#include <calf/giface.h>
#include <calf/modules_synths.h>
#include <iostream>
using namespace dsp;
using namespace calf_plugins;
wavetable_voice::wavetable_voice()
{
sample_rate = -1;
}
void wavetable_voice::set_params_ptr(wavetable_audio_module *_parent, int _srate)
{
parent = _parent;
params = parent->params;
sample_rate = _srate;
}
void wavetable_voice::reset()
{
note = -1;
}
void wavetable_voice::note_on(int note, int vel)
{
typedef wavetable_metadata md;
this->note = note;
velocity = vel / 127.0;
amp.set(1.0);
for (int i = 0; i < OscCount; i++) {
oscs[i].reset();
oscs[i].set_freq(note_to_hz(note, 0), sample_rate);
last_oscshift[i] = 0;
}
int cr = sample_rate / BlockSize;
for (int i = 0; i < EnvCount; i++) {
envs[i].set(0.01, 0.1, 0.5, 1, cr);
envs[i].note_on();
}
float modsrc[wavetable_metadata::modsrc_count] = { 1, velocity, parent->inertia_pressure.get_last(), parent->modwheel_value, envs[0].value, envs[1].value, envs[2].value};
parent->calculate_modmatrix(moddest, md::moddest_count, modsrc);
calc_derived_dests();
float oscshift[2] = { moddest[md::moddest_o1shift], moddest[md::moddest_o2shift] };
memcpy(last_oscshift, oscshift, sizeof(oscshift));
memcpy(last_oscamp, cur_oscamp, sizeof(cur_oscamp));
}
void wavetable_voice::note_off(int vel)
{
for (int i = 0; i < EnvCount; i++)
envs[i].note_off();
}
void wavetable_voice::steal()
{
}
void wavetable_voice::render_block()
{
typedef wavetable_metadata md;
const float step = 1.f / BlockSize;
float s = 0.001;
float scl[EnvCount];
int espc = md::par_eg2attack - md::par_eg1attack;
for (int j = 0; j < EnvCount; j++) {
int o = j*espc;
envs[j].set(*params[md::par_eg1attack + o] * s, *params[md::par_eg1decay + o] * s, *params[md::par_eg1sustain + o], *params[md::par_eg1release + o] * s, sample_rate / BlockSize, *params[md::par_eg1fade + o] * s);
scl[j] = dsp::lerp(1.f, velocity, *params[md::par_eg1velscl + o]);;
}
for (int i = 0; i < EnvCount; i++)
envs[i].advance();
float modsrc[wavetable_metadata::modsrc_count] = { 1, velocity, parent->inertia_pressure.get_last(), parent->modwheel_value, envs[0].value, envs[1].value, envs[2].value};
parent->calculate_modmatrix(moddest, md::moddest_count, modsrc);
calc_derived_dests();
int ospc = md::par_o2level - md::par_o1level;
for (int j = 0; j < OscCount; j++) {
oscs[j].tables = parent->tables[(int)*params[md::par_o1wave + j * ospc]];
oscs[j].set_freq(note_to_hz(note, *params[md::par_o1transpose + j * ospc] * 100+ *params[md::par_o1detune + j * ospc] + moddest[md::moddest_o1detune]), sample_rate);
}
float oscshift[2] = { moddest[md::moddest_o1shift], moddest[md::moddest_o2shift] };
float osstep[2] = { (oscshift[0] - last_oscshift[0]) * step, (oscshift[1] - last_oscshift[1]) * step };
float oastep[2] = { (cur_oscamp[0] - last_oscamp[0]) * step, (cur_oscamp[1] - last_oscamp[1]) * step };
for (int i = 0; i < BlockSize; i++) {
float value = 0.f;
for (int j = 0; j < OscCount; j++) {
float o = last_oscshift[j] * 0.01;
value += last_oscamp[j] * oscs[j].get(dsp::clip(fastf2i_drm((o + *params[md::par_o1offset + j * ospc]) * 127.0 * 256), 0, 127 * 256));
last_oscshift[j] += osstep[j];
last_oscamp[j] += oastep[j];
}
output_buffer[i][0] = output_buffer[i][1] = value;
}
if (envs[0].stopped())
released = true;
memcpy(last_oscshift, oscshift, sizeof(oscshift));
memcpy(last_oscamp, cur_oscamp, sizeof(cur_oscamp));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
static inline float sincl(float x, float clip)
{
if (fabs(x) > clip)
return 0;
return sin(M_PI * x);
}
static inline float blip(float x, float center, float range)
{
if (x < center - range || x > center + range)
return 0;
return 1 - fabs(x - center)/range;
}
static void interpolate_wt(int16_t table[129][256], int step)
{
for (int i = 0; i < 128; i++)
{
if (!(i % step))
continue;
int prev = i - i % step;
int next = prev + step;
for (int j = 0; j < 256; j++)
{
table[i][j] = table[prev][j] + (i - prev) * (table[next][j] - table[prev][j]) / step;
}
}
}
wavetable_audio_module::wavetable_audio_module()
: mod_matrix_impl(mod_matrix_data, &mm_metadata)
, inertia_cutoff(1)
, inertia_pitchbend(1)
, inertia_pressure(64)
{
panic_flag = false;
modwheel_value = 0.;
for (int i = 0; i < 129; i += 8)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
int harm = 1 + 2 * (i / 8);
float ii = i / 128.0;
float rezo1 = sin(harm * ph) * sin(ph);
float rezo2 = sin((harm+1) * ph) * sin(ph * 2);
float rezo3 = sin((harm+3) * ph) * sin(ph * 4);
float rezo = (rezo1 + rezo2 + rezo3) / 3;
float v = (sin (ph) + ii * ii * rezo) / 2;
tables[0][i][j] = 32767 * v;
}
}
interpolate_wt(tables[0], 8);
for (int i = 0; i < 129; i += 4)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
int harm = 1 + (i / 4);
float ii = i / 128.0;
float h = sin(harm * ph);
float rezo1 = h * sin(ph);
float rezo2 = h * sin(ph * 2)/2;
float rezo3 = h * sin(ph * 3)/3;
float rezo4 = h * sin(ph * 4)/4;
float rezo5 = h * sin(ph * 5)/5;
float rezo = (rezo1 + rezo2 + rezo3 + rezo4 + rezo5) / 3;
float v = sin (ph + ii * rezo);
tables[1][i][j] = 32767 * v;
}
}
interpolate_wt(tables[1], 4);
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = (i & ~3) / 128.0;
float ii2 = ((i & ~3) + 4) / 128.0;
float peak = (32 * ii);
float rezo1 = sin(floor(peak) * ph);
float rezo2 = sin(floor(peak + 1) * ph);
float widener = (0.5 + 0.3 * sin(ph) + 0.2 * sin (3 * ph));
float v1 = 0.5 * sin (ph) + 0.5 * ii * ii * rezo1 * widener;
float v2 = 0.5 * sin (ph) + 0.5 * ii2 * ii2 * rezo2 * widener;
tables[wavetable_metadata::wt_rezo][i][j] = 32767 * lerp(v1, v2, (i & 3) / 4.0);
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float v = (sin(ph) + ii * sin(ph + 2 * ii * sin(ph)) + ii * ii * sin(ph + 6 * ii * ii * sin(6 * ph)) + ii * ii * ii * ii * sin(ph + 11 * ii * ii * ii * ii * sin(11 * ph))) / 4;
tables[wavetable_metadata::wt_metal][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float v = (sin(ph) + ii * sin(ph - 3 * ii * sin(ph)) + ii * ii * sin(5 * ph - 5 * ii * ii * ii * ii * sin(11 * ph))) / 3;
tables[wavetable_metadata::wt_bell][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
//float v = (sin(ph) + ii * sin(ph + 2 * ii * sin(ph)) + ii * ii * sin(ph + 3 * ii * ii * sin(3 * ph)) + ii * ii * ii * sin(ph + 5 * ii * ii * ii * sin(5 * ph))) / 4;
float v = (sin(ph) + sin(ph - 3 * sin(ii * 5 - 2) * sin(ph)) + sin(ii * 4 - 1.3) * sin(5 * ph + 3 * ii * ii * sin(6 * ph))) / 3;
tables[wavetable_metadata::wt_blah][i][j] = 32767 * v;
}
}
for (int i = 0; i < 256; i++)
{
tables[wavetable_metadata::wt_pluck][128][i] = (i < 128) ? 32000 * fabs(sin(i / 32.0 * M_PI) * sin(i / 13.0 * M_PI) * sin(i / 19.0 * M_PI)) : 0;
}
for (int i = 127; i >= 0; i--)
{
int16_t *parent = tables[wavetable_metadata::wt_pluck][i + 1];
float damp = 0.05;
for (int j = 0; j < 256; j++)
{
tables[wavetable_metadata::wt_pluck][i][j] = (1 - 2*damp) * parent[j] + damp * parent[(j+1)&255] + damp * parent[(j+2)&255];// + 0.1 * parent[(j-1)&255]+ 0.1 * parent[(j-2)&255];
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j / 128.0 - 1.0;
float ii = i / 128.0;
float v = sincl(ph * (1 + 15 * ii), 1);
tables[wavetable_metadata::wt_stretch][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j / 128.0 - 1.0;
float ii = i / 128.0;
float v = sincl(ph * (1 + 15 * ii), 4) * sincl(j / 256.0, 1);
tables[wavetable_metadata::wt_stretch2][i][j] = 32000 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j / 128.0 - 1.0;
float ii = i / 128.0;
float w = sincl(ph * (1 + 15 * ii), 4);
float v = pow(w, 9) * sincl(j / 256.0, 1);
tables[wavetable_metadata::wt_hardsync][i][j] = 32000 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j / 128.0 - 1.0;
float ii = i / 128.0;
float w = sincl(ph * (1 + 31 * ii), 3);
float v = pow(w, 5) * sincl(j / 256.0, 1);
tables[wavetable_metadata::wt_hardsync2][i][j] = 32000 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j / 128.0 - 1.0;
float ii = i / 128.0;
float w = sincl(ph * ph * (1 + 15 * ii), 2);
float v = pow(w, 4) * sincl(j / 256.0, 1);
tables[wavetable_metadata::wt_softsync][i][j] = 32000 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float v = (sin(ph) + ii * sin(ph - 3 * ii * sin(ph)) + ii * ii * ii * sin(7 * ph - 2 * ii * ii * ii * ii * sin(13 * ph))) / 3;
tables[wavetable_metadata::wt_bell2][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float v = (sin(ph) + ii * sin(ph - 3 * ii * sin(ph)) + ii * ii * ii * sin(9 * ph - ii * ii * sin(11 * ph))) / 3;
tables[wavetable_metadata::wt_bell3][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float v = (sin(ph + ii * sin(ph - 3 * ii * sin(ph) + ii * ii * ii * sin(5 * ph - ii * ii * sin(7 * ph)))));
tables[wavetable_metadata::wt_tine][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float v = (sin(ph + ii * sin(ph - 2 * ii * sin(ph) + ii * ii * ii * sin(3 * ph - ii * ii * sin(4 * ph)))));
tables[wavetable_metadata::wt_tine2][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ph2 = j / 128.0 - 1;
float ii = i / 128.0;
float w = sincl(ph2 * (1 + 7 * ii * ii), 4) * pow(sincl(j / 256.0, 1), 2);
float v = sin(ph + ii * sin(ph - 2 * ii * w));
tables[wavetable_metadata::wt_clav][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ph2 = j / 128.0 - 1;
float ii = i / 128.0;
float w = sincl(ph2 * (1 + 7 * ii * ii), 6) * sincl(j / 256.0, 1);
float v = sin(ph + ii * sin(3 * ph - 2 * ii * w));
tables[wavetable_metadata::wt_clav2][i][j] = 32767 * v;
}
}
/*
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ph2 = j / 128.0 - 1;
float ii = i / 128.0;
float w = sincl(ph2 * (1 + 7 * ii * ii), 6) * pow(sincl(j / 256.0, 1), 1);
float v = sin(ph + ii * ii * ii * sin(3 * ph - ii * ii * ii * w));
tables[wavetable_metadata::wt_gtr][i][j] = 32767 * v;
}
}
*/
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float ii2 = ii;
float w = pow(sincl(j / 256.0, 1), 1);
float v = sin(ph + ii2 * ii2 * ii2 * sin(3 * ph - ii2 * ii2 * ii2 * w * sin(ph + sin(3 * ph) + ii * sin(11 * ph) + ii * ii * sin(25 * ph))));
tables[wavetable_metadata::wt_gtr][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float ii2 = dsp::clip(ii - 0.5, 0.0, 1.0);
float w = pow(sincl(j / 256.0, 1), 1);
float v = sin(ph + ii * ii * ii * sin(3 * ph - ii * ii * ii * w * sin(ph + sin(3 * ph + ii2 * sin(13 * ph)))));
tables[wavetable_metadata::wt_gtr2][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float ii2 = dsp::clip(2 * (ii - 0.5), 0.0, 1.0);
//float w = sincl(ph2 * (1 + 15 * ii2 * ii2), 4) * pow(sincl(j / 256.0, 1), 1);
float w = pow(sincl(j / 256.0, 1), 1);
float v = sin(ph + ii * sin(3 * ph - ii * w * sin(ph + sin(3 * ph + 0.5 * ii2 * sin(13 * ph + 0.5 * sin(4 * ph))))));
tables[wavetable_metadata::wt_gtr3][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float ii2 = dsp::clip(2 * (ii - 0.5), 0.0, 1.0);
//float w = sincl(ph2 * (1 + 15 * ii2 * ii2), 4) * pow(sincl(j / 256.0, 1), 1);
float w = pow(sincl(j / 256.0, 1), 1);
float v = sin(ph + ii * sin(3 * ph - ii * w * sin(2 * ph + sin(5 * ph + 0.5 * ii2 * sin(13 * ph + 0.5 * sin(4 * ph))))));
tables[wavetable_metadata::wt_gtr4][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float ii2 = dsp::clip((ii - 0.25)/0.75, 0.0, 1.0);
//float w = sincl(ph2 * (1 + 15 * ii2 * ii2), 4) * pow(sincl(j / 256.0, 1), 1);
float w = pow(sincl(j / 256.0, 1), 3);
float v = sin(ph + (ii + 0.05) * sin(3 * ph - 2 * ii * w * sin(5 * ph + sin(7 * ph + 0.5 * ii2 * sin(13 * ph + 0.5 * sin(11 * ph))))));
tables[wavetable_metadata::wt_gtr5][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float w = pow(sincl(2 * (j / 256.0), 2), 3);
float v = sin(ph + (ii + 0.05) * sin(7 * ph - 2 * ii * w * sin(11 * ph)));
tables[wavetable_metadata::wt_reed][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float ii2 = dsp::clip((ii - 0.25)/0.75, 0.0, 1.0);
float ii3 = dsp::clip((ii - 0.5)/0.5, 0.0, 1.0);
float v = sin(ph + (ii + 0.05) * sin(ii * sin(2 * ph) - 2 * ii2 * sin(2 * ph + ii2 * sin(3 * ph)) + 3 * ii3 * sin(3 * ph)));
tables[wavetable_metadata::wt_reed2][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float mod = 0;
for (int k = 0; k < 13; k++)
{
mod += blip(i, k * 10, 30) * sin (ph * (5 + 3 * k) + ii * cos(ph * (2 + 2 * k)));
}
float v = sin(ph + ii * mod);
tables[wavetable_metadata::wt_silver][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float mod = 0;
for (int k = 0; k < 16; k++)
{
mod += 2 * blip(i, k * 8, k * 4 + 10) * cos (ph * (k + 1));
}
float v = sin(ph + ii * mod);
tables[wavetable_metadata::wt_brass][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i++)
{
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float ii = i / 128.0;
float mod = 0;
for (int k = 0; k < 16; k++)
{
mod += 2 * blip(i, k * 8, 16) * cos (ph * (2 * k + 1));
}
float v = (sin(ph + ii * mod) + ii * sin(2 * ph + ii * mod)) / 2;
tables[wavetable_metadata::wt_multi][i][j] = 32767 * v;
}
}
for (int i = 0; i < 129; i ++)
{
float h = 1 + i / 16.0;
for (int j = 0; j < 256; j++)
{
float ph = j * 2 * M_PI / 256;
float v = sin(ph), tv = 1;
for (int k = 1; k < 24; k++) {
float amp = blip(i, k * 6, 20) / k;
v += amp * sin((k + 1) * ph + h * sin(ph));
tv += amp;
}
tables[wavetable_metadata::wt_multi2][i][j] = 32767 * v / tv;
}
}
}
void wavetable_audio_module::channel_pressure(int value)
{
inertia_pressure.set_inertia(value * (1.0 / 127.0));
}
#endif