[SCM] calf/master: + Wavetable: initial work at adding mod matrix to wavetable, very incomplete/broken
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:39:33 UTC 2013
The following commit has been merged in the master branch:
commit 759ef0e2cf444cd7ba72481ac544f34c27dccc46
Author: Krzysztof Foltman <wdev at foltman.com>
Date: Wed May 20 00:13:55 2009 +0100
+ Wavetable: initial work at adding mod matrix to wavetable, very incomplete/broken
diff --git a/gui/gui-wavetable.xml b/gui/gui-wavetable.xml
index 2591e15..c79ea7b 100644
--- a/gui/gui-wavetable.xml
+++ b/gui/gui-wavetable.xml
@@ -90,6 +90,7 @@
<value attach-x="5" attach-y="6" param="adsr3_r"/>
<value attach-x="6" attach-y="6" param="adsr3_v"/>
</table>
+ <listview param="adsr_s" />
</vbox>
</frame>
</vbox>
diff --git a/src/calf/metadata.h b/src/calf/metadata.h
index 8f4a60a..4d2bd0c 100644
--- a/src/calf/metadata.h
+++ b/src/calf/metadata.h
@@ -274,22 +274,24 @@ struct wavetable_metadata: public plugin_metadata<wavetable_metadata>
};
enum {
modsrc_none,
+ modsrc_velocity,
+ modsrc_pressure,
+ modsrc_modwheel,
modsrc_env1,
modsrc_env2,
modsrc_env3,
- modsrc_velocity,
- modsrc_modwheel,
modsrc_count,
};
enum {
moddest_none,
+ moddest_attenuation,
+ moddest_oscmix,
+ moddest_cutoff,
+ moddest_resonance,
moddest_o1shift,
moddest_o2shift,
moddest_o1detune,
moddest_o2detune,
- moddest_o1pitch,
- moddest_o2pitch,
- moddest_dca,
moddest_count,
};
enum {
@@ -298,6 +300,7 @@ struct wavetable_metadata: public plugin_metadata<wavetable_metadata>
par_eg1attack, par_eg1decay, par_eg1sustain, par_eg1fade, par_eg1release, par_eg1velscl,
par_eg2attack, par_eg2decay, par_eg2sustain, par_eg2fade, par_eg2release, par_eg2velscl,
par_eg3attack, par_eg3decay, par_eg3sustain, par_eg3fade, par_eg3release, par_eg3velscl,
+ par_pwhlrange,
param_count };
enum { in_count = 0, out_count = 2, support_midi = true, require_midi = true, rt_capable = true };
enum { step_size = 64 };
diff --git a/src/calf/modmatrix.h b/src/calf/modmatrix.h
index 580e443..88cbba2 100644
--- a/src/calf/modmatrix.h
+++ b/src/calf/modmatrix.h
@@ -18,6 +18,9 @@
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02111-1307, USA.
*/
+#ifndef __CALF_MODMATRIX_H
+#define __CALF_MODMATRIX_H
+
#include "giface.h"
namespace dsp {
@@ -63,3 +66,5 @@ public:
};
};
+
+#endif
diff --git a/src/calf/wavetable.h b/src/calf/wavetable.h
index a7c6a9e..a553538 100644
--- a/src/calf/wavetable.h
+++ b/src/calf/wavetable.h
@@ -9,6 +9,7 @@
#include "osc.h"
#include "synth.h"
#include "envelope.h"
+#include "modmatrix.h"
namespace calf_plugins {
@@ -54,13 +55,23 @@ protected:
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() {
@@ -70,9 +81,14 @@ public:
// 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
+class wavetable_audio_module: public audio_module<wavetable_metadata>, public dsp::basic_synth, public mod_matrix
{
public:
using dsp::basic_synth::note_on;
@@ -85,10 +101,21 @@ protected:
bool panic_flag;
public:
+ enum { mod_matrix_slots = 10 };
float *ins[in_count];
float *outs[out_count];
float *params[param_count];
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();
@@ -122,6 +149,16 @@ public:
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)));
}
};
diff --git a/src/modules.cpp b/src/modules.cpp
index 9e8f2a4..048eb93 100644
--- a/src/modules.cpp
+++ b/src/modules.cpp
@@ -601,6 +601,7 @@ CALF_PORT_PROPS(wavetable) = {
{ 50, 10, 20000, 0, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "adsr3_r", "EG3 Release" },
{ 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" },
};
////////////////////////////////////////////////////////////////////////////
diff --git a/src/wavetable.cpp b/src/wavetable.cpp
index 3f0ac01..2da7993 100644
--- a/src/wavetable.cpp
+++ b/src/wavetable.cpp
@@ -35,6 +35,30 @@
using namespace dsp;
using namespace calf_plugins;
+static const char *mod_src_names[] = {
+ "None",
+ "Velocity",
+ "Pressure",
+ "ModWheel",
+ "Env 1",
+ "Env 2",
+ "Env 3",
+ NULL
+};
+
+static const char *mod_dest_names[] = {
+ "None",
+ "Attenuation",
+ "Osc Mix Ratio (%)",
+ "Cutoff [ct]",
+ "Resonance",
+ "O1: Shift (%)",
+ "O2: Shift (%)",
+ "O1: Detune [ct]",
+ "O2: Detune [ct]",
+ NULL
+};
+
wavetable_voice::wavetable_voice()
{
sample_rate = -1;
@@ -54,18 +78,27 @@ void wavetable_voice::reset()
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)
@@ -84,14 +117,9 @@ void wavetable_voice::render_block()
const float step = 1.f / BlockSize;
- int ospc = md::par_o2level - md::par_o1level;
- int espc = md::par_eg2attack - md::par_eg1attack;
- 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]), sample_rate);
- }
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);
@@ -101,20 +129,35 @@ void wavetable_voice::render_block()
for (int i = 0; i < EnvCount; i++)
envs[i].advance();
- float env_old = envs[0].old_value * scl[0] + 0.2 * envs[1].old_value * scl[1];
- float env_new = envs[0].value * scl[0] + 0.2 * envs[1].value * scl[1];
+ 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;
- float env = dsp::lerp(env_old, env_new, i * step);
for (int j = 0; j < OscCount; j++) {
- value += oscs[j].get(dsp::clip(fastf2i_drm((env + *params[md::par_o1offset + j * ospc]) * 127.0 * 256), 0, 127 * 256)) * *params[md::par_o1level + j * ospc];
+ 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 * env * env;
+ 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));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -149,8 +192,13 @@ static void interpolate_wt(int16_t table[129][256], int step)
}
wavetable_audio_module::wavetable_audio_module()
+: mod_matrix(mod_matrix_data, mod_matrix_slots, ::mod_src_names, ::mod_dest_names)
+, 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++)
@@ -525,4 +573,9 @@ wavetable_audio_module::wavetable_audio_module()
}
}
+void wavetable_audio_module::channel_pressure(int value)
+{
+ inertia_pressure.set_inertia(value * (1.0 / 127.0));
+}
+
#endif
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list