Reimplement modulation matrix (and tables in general) using configure variables. Slow and most likely incomplete, but a good start.

This commit is contained in:
Krzysztof Foltman
2010-12-02 21:06:45 +00:00
committed by Tobias Doerffel
parent 8053f5adcf
commit 43e2886e79
12 changed files with 973 additions and 182 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
@@ -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
@@ -482,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,8 +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);
/// Lookup of table edit interface
virtual table_edit_iface *get_table_edit_iface(const char *key) { if (!strcmp(key, "mod_matrix")) return static_cast<mod_matrix *>(this); else return NULL; }
/// 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

@@ -777,6 +777,37 @@ CALF_PORT_PROPS(monosynth) = {
{}
};
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" };
@@ -1037,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",
@@ -1083,6 +1136,11 @@ CALF_PORT_PROPS(wavetable) = {
{}
};
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

@@ -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

@@ -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