[SCM] calf/master: + Organ: ruined perfectly good tonewheel organ wannabe by adding settable drawbar frequencies and more waveforms (including Farfisa-esque pulse), unfortunately there is no UI for setting waveforms yet + Monosynth: normalize -> normalize_waveform, made a global static function
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:37:05 UTC 2013
The following commit has been merged in the master branch:
commit 9ec053dbaf498ac9630c98cfdb2b743134ce99f0
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date: Thu Mar 20 00:00:49 2008 +0000
+ Organ: ruined perfectly good tonewheel organ wannabe by adding settable drawbar frequencies and more waveforms (including Farfisa-esque pulse), unfortunately there is no UI for setting waveforms yet
+ Monosynth: normalize -> normalize_waveform, made a global static function
git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@134 78b06b96-2940-0410-b7fc-879d825d01d8
diff --git a/src/calf/modules_synths.h b/src/calf/modules_synths.h
index 6998d97..4b4cf84 100644
--- a/src/calf/modules_synths.h
+++ b/src/calf/modules_synths.h
@@ -31,7 +31,7 @@
namespace synth {
-#define MONOSYNTH_WAVE_SIZE 12
+#define MONOSYNTH_WAVE_BITS 12
/// 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.
@@ -48,8 +48,8 @@ public:
float *outs[out_count];
float *params[param_count];
uint32_t srate, crate;
- static waveform_family<MONOSYNTH_WAVE_SIZE> waves[wave_count];
- waveform_oscillator<MONOSYNTH_WAVE_SIZE> osc1, osc2;
+ static waveform_family<MONOSYNTH_WAVE_BITS> waves[wave_count];
+ waveform_oscillator<MONOSYNTH_WAVE_BITS> osc1, osc2;
bool running, stopping, gate;
int last_key;
@@ -196,7 +196,11 @@ public:
using drawbar_organ::note_on;
using drawbar_organ::note_off;
using drawbar_organ::control_change;
- enum { par_drawbar1, par_drawbar2, par_drawbar3, par_drawbar4, par_drawbar5, par_drawbar6, par_drawbar7, par_drawbar8, par_drawbar9, par_foldover,
+ enum {
+ par_drawbar1, par_drawbar2, par_drawbar3, par_drawbar4, par_drawbar5, par_drawbar6, par_drawbar7, par_drawbar8, par_drawbar9,
+ par_frequency1, par_frequency2, par_frequency3, par_frequency4, par_frequency5, par_frequency6, par_frequency7, par_frequency8, par_frequency9,
+ par_waveform1, par_waveform2, par_waveform3, par_waveform4, par_waveform5, par_waveform6, par_waveform7, par_waveform8, par_waveform9,
+ par_foldover,
par_percdecay, par_perclevel, par_percharm, par_master, param_count };
enum { in_count = 0, out_count = 2, support_midi = true, rt_capable = true };
static const char *port_names[];
diff --git a/src/calf/organ.h b/src/calf/organ.h
index 9498c3b..594de2d 100644
--- a/src/calf/organ.h
+++ b/src/calf/organ.h
@@ -29,6 +29,8 @@ namespace synth
struct organ_parameters {
float drawbars[9];
+ float harmonics[9];
+ float waveforms[9];
float foldover;
float percussion_time;
float percussion_level;
@@ -41,16 +43,24 @@ struct organ_parameters {
inline int get_harmonic() { return dsp::fastf2i_drm(harmonic); }
};
+#define ORGAN_WAVE_BITS 12
+#define ORGAN_WAVE_SIZE 4096
+
class organ_voice_base
{
protected:
- dsp::sine_table<float, 4096, 1> sine_wave;
+ enum { wave_sine, wave_pulse, wave_stretchsine, wave_count };
+ static waveform_family<ORGAN_WAVE_BITS> waves[wave_count];
+ // dsp::sine_table<float, ORGAN_WAVE_SIZE, 1> sine_wave;
dsp::fixed_point<int, 20> phase, dphase;
int note;
dsp::decay amp;
+ organ_parameters *parameters;
- inline float sine(dsp::fixed_point<int, 20> ph) {
- return ph.lerp_table_lookup_float(sine_wave.data);
+ organ_voice_base(organ_parameters *_parameters);
+
+ inline float wave(float *data, dsp::fixed_point<int, 20> ph) {
+ return ph.lerp_table_lookup_float(data);
}
};
@@ -59,11 +69,10 @@ protected:
bool released;
int h4, h6, h8, h12, h16;
dsp::fixed_point<int, 3> h10;
- organ_parameters *parameters;
public:
organ_voice(organ_parameters *_parameters)
- : parameters(_parameters) {
+ : organ_voice_base(_parameters) {
}
void reset() {
@@ -108,22 +117,45 @@ public:
if (!amp.get_active())
dsp::zero(buf[0], nsamples);
else {
- for (int i=0; i<nsamples; i++) {
-// float osc = 0.2*sine(phase)+0.1*sine(4*phase)+0.08*sine(12*phase)+0.08*sine(16*phase);
- float *drawbars = parameters->drawbars;
- float osc =
- drawbars[0]*sine(phase)+
- drawbars[1]*sine(3*phase)+
- drawbars[2]*sine(2*phase)+
- drawbars[3]*sine(h4*phase)+
- drawbars[4]*sine(h6*phase)+
- drawbars[5]*sine(h8*phase)+
- drawbars[6]*sine(h10*phase)+
- drawbars[7]*sine(h12*phase)+
- drawbars[8]*sine(h16*phase);
- buf[0][i] += osc*amp.get();
- if (released) amp.age_lin((1.0/44100.0)/0.03,0.0);
- phase += dphase;
+ float tmp[256], *sig;
+ if (released)
+ {
+ sig = tmp;
+ for (int i=0; i<nsamples; i++)
+ tmp[i] = 0;
+ }
+ else
+ sig = buf[0];
+ dsp::fixed_point<int, 20> tphase, tdphase;
+ for (int h = 0; h < 9; h++)
+ {
+ float *data;
+ dsp::fixed_point<int, 24> hm = dsp::fixed_point<int, 24>(parameters->harmonics[h]);
+ int waveid = (int)parameters->waveforms[h];
+ if (waveid < 0 || waveid >= wave_count)
+ waveid = 0;
+ do {
+ data = waves[waveid].get_level((dphase * hm).get());
+ if (data)
+ break;
+ hm.set(hm.get() >> 1);
+ } while(1);
+ tphase = phase * hm;
+ tdphase = dphase * hm;
+ float amp = parameters->drawbars[h];
+ for (int i=0; i<nsamples; i++) {
+ // float osc = 0.2*sine(phase)+0.1*sine(4*phase)+0.08*sine(12*phase)+0.08*sine(16*phase);
+ sig[i] += wave(data, tphase)*amp;
+ tphase += tdphase;
+ }
+ }
+ phase += dphase * nsamples;
+ if (released)
+ {
+ for (int i=0; i<nsamples; i++) {
+ buf[0][i] += tmp[i] * amp.get();
+ amp.age_lin((1.0/44100.0)/0.03,0.0);
+ }
}
}
}
@@ -138,13 +170,11 @@ public:
/// Not a true voice, just something with similar-ish interface.
class percussion_voice: public organ_voice_base {
public:
- organ_parameters *parameters;
int sample_rate;
percussion_voice(organ_parameters *_parameters)
+ : organ_voice_base(_parameters)
{
- parameters = _parameters;
- note = -1;
}
void reset() {
phase = 0;
@@ -171,8 +201,9 @@ public:
float level = parameters->percussion_level * (8 * 9);
// XXXKF the decay needs work!
double age_const = parameters->perc_decay_const;
+ float *data = waves[wave_sine].begin()->second;
for (int i = 0; i < nsamples; i++) {
- float osc = level * sine(harmonic * phase);
+ float osc = level * wave(data, harmonic * phase);
buf[i] += osc * amp.get();
amp.age_exp(age_const, 1.0 / 32768.0);
phase += dphase;
diff --git a/src/calf/osc.h b/src/calf/osc.h
index 6e85998..4f89a6f 100644
--- a/src/calf/osc.h
+++ b/src/calf/osc.h
@@ -138,6 +138,19 @@ struct waveform_oscillator: public simple_oscillator
}
};
+static inline void normalize_waveform(float *table, unsigned int size)
+{
+ float thismax = 0;
+ for (unsigned int i = 0; i < size; i++)
+ thismax = std::max(thismax, fabs(table[i]));
+ if (thismax < 0.000001f)
+ return;
+ for (unsigned int i = 0; i < size; i++)
+ table[i] /= thismax;
+}
+
+
+
};
#endif
diff --git a/src/monosynth.cpp b/src/monosynth.cpp
index 6f22eb8..e1eb66b 100644
--- a/src/monosynth.cpp
+++ b/src/monosynth.cpp
@@ -228,17 +228,6 @@ const char *monosynth_audio_module::get_gui_xml()
return monosynth_gui_xml;
}
-static void normalize(float *table, unsigned int size)
-{
- float thismax = 0;
- for (unsigned int i = 0; i < size; i++)
- thismax = std::max(thismax, fabs(table[i]));
- if (thismax < 0.000001f)
- return;
- for (unsigned int i = 0; i < size; i++)
- table[i] /= thismax;
-}
-
void monosynth_audio_module::activate() {
running = false;
output_pos = 0;
@@ -250,14 +239,14 @@ void monosynth_audio_module::activate() {
stack.clear();
}
-waveform_family<MONOSYNTH_WAVE_SIZE> monosynth_audio_module::waves[wave_count];
+waveform_family<MONOSYNTH_WAVE_BITS> monosynth_audio_module::waves[wave_count];
void monosynth_audio_module::generate_waves()
{
- float data[1 << MONOSYNTH_WAVE_SIZE];
- bandlimiter<MONOSYNTH_WAVE_SIZE> bl;
+ float data[1 << MONOSYNTH_WAVE_BITS];
+ bandlimiter<MONOSYNTH_WAVE_BITS> bl;
- enum { S = 1 << MONOSYNTH_WAVE_SIZE, HS = S / 2, QS = S / 4, QS3 = 3 * QS };
+ enum { S = 1 << MONOSYNTH_WAVE_BITS, HS = S / 2, QS = S / 4, QS3 = 3 * QS };
float iQS = 1.0 / QS;
// yes these waves don't have really perfect 1/x spectrum because of aliasing
@@ -317,7 +306,7 @@ void monosynth_audio_module::generate_waves()
for (int i = 0; i < S; i++) {
data[i] = exp(-i * 1.0 / HS) * sin(i * PI / HS) * cos(2 * PI * i / HS);
}
- normalize(data, S);
+ normalize_waveform(data, S);
waves[wave_test2].make(bl, data);
for (int i = 0; i < S; i++) {
//int ii = (i < HS) ? i : S - i;
@@ -347,12 +336,12 @@ void monosynth_audio_module::generate_waves()
}
waves[wave_test6].make(bl, data);
for (int i = 0; i < S; i++) {
- int j = i >> (MONOSYNTH_WAVE_SIZE - 11);
+ int j = i >> (MONOSYNTH_WAVE_BITS - 11);
data[i] = (j ^ 0x1D0) * 1.0 / HS - 1;
}
waves[wave_test7].make(bl, data);
for (int i = 0; i < S; i++) {
- int j = i >> (MONOSYNTH_WAVE_SIZE - 11);
+ int j = i >> (MONOSYNTH_WAVE_BITS - 11);
data[i] = -1 + 0.66 * (3 & ((j >> 8) ^ (j >> 10) ^ (j >> 6)));
}
waves[wave_test8].make(bl, data);
@@ -368,7 +357,7 @@ bool monosynth_audio_module::get_static_graph(int index, int subindex, float val
if (index == par_wave1 || index == par_wave2) {
if (subindex)
return false;
- enum { S = 1 << MONOSYNTH_WAVE_SIZE };
+ enum { S = 1 << MONOSYNTH_WAVE_BITS };
int wave = dsp::clip(dsp::fastf2i_drm(value), 0, (int)wave_count - 1);
float *waveform = waves[wave].get_level(0);
diff --git a/src/organ.cpp b/src/organ.cpp
index bee8941..08f88d1 100644
--- a/src/organ.cpp
+++ b/src/organ.cpp
@@ -62,42 +62,60 @@ const char *organ_audio_module::get_gui_xml()
"<value param=\"master\"/>"
"</vbox>"
"</hbox>"
- "<table rows=\"3\" cols=\"9\">"
+ "<table rows=\"5\" cols=\"9\">"
"<label attach-x=\"0\" attach-y=\"0\" param=\"h1\"/>"
"<vscale attach-x=\"0\" attach-y=\"1\" param=\"h1\"/>"
"<value attach-x=\"0\" attach-y=\"2\" param=\"h1\"/>"
+ "<knob attach-x=\"0\" attach-y=\"3\" param=\"f1\"/>"
+ "<value attach-x=\"0\" attach-y=\"4\" param=\"f1\"/>"
"<label attach-x=\"1\" attach-y=\"0\" param=\"h3\"/>"
"<vscale attach-x=\"1\" attach-y=\"1\" param=\"h3\"/>"
"<value attach-x=\"1\" attach-y=\"2\" param=\"h3\"/>"
+ "<knob attach-x=\"1\" attach-y=\"3\" param=\"f2\"/>"
+ "<value attach-x=\"1\" attach-y=\"4\" param=\"f2\"/>"
"<label attach-x=\"2\" attach-y=\"0\" param=\"h2\"/>"
"<vscale attach-x=\"2\" attach-y=\"1\" param=\"h2\"/>"
"<value attach-x=\"2\" attach-y=\"2\" param=\"h2\"/>"
+ "<knob attach-x=\"2\" attach-y=\"3\" param=\"f3\"/>"
+ "<value attach-x=\"2\" attach-y=\"4\" param=\"f3\"/>"
"<label attach-x=\"3\" attach-y=\"0\" param=\"h4\"/>"
"<vscale attach-x=\"3\" attach-y=\"1\" param=\"h4\"/>"
"<value attach-x=\"3\" attach-y=\"2\" param=\"h4\"/>"
+ "<knob attach-x=\"3\" attach-y=\"3\" param=\"f4\"/>"
+ "<value attach-x=\"3\" attach-y=\"4\" param=\"f4\"/>"
"<label attach-x=\"4\" attach-y=\"0\" param=\"h6\"/>"
"<vscale attach-x=\"4\" attach-y=\"1\" param=\"h6\"/>"
"<value attach-x=\"4\" attach-y=\"2\" param=\"h6\"/>"
+ "<knob attach-x=\"4\" attach-y=\"3\" param=\"f5\"/>"
+ "<value attach-x=\"4\" attach-y=\"4\" param=\"f5\"/>"
"<label attach-x=\"5\" attach-y=\"0\" param=\"h8\"/>"
"<vscale attach-x=\"5\" attach-y=\"1\" param=\"h8\"/>"
"<value attach-x=\"5\" attach-y=\"2\" param=\"h8\"/>"
+ "<knob attach-x=\"5\" attach-y=\"3\" param=\"f6\"/>"
+ "<value attach-x=\"5\" attach-y=\"4\" param=\"f6\"/>"
"<label attach-x=\"6\" attach-y=\"0\" param=\"h10\"/>"
"<vscale attach-x=\"6\" attach-y=\"1\" param=\"h10\"/>"
"<value attach-x=\"6\" attach-y=\"2\" param=\"h10\"/>"
+ "<knob attach-x=\"6\" attach-y=\"3\" param=\"f7\"/>"
+ "<value attach-x=\"6\" attach-y=\"4\" param=\"f7\"/>"
"<label attach-x=\"7\" attach-y=\"0\" param=\"h12\"/>"
"<vscale attach-x=\"7\" attach-y=\"1\" param=\"h12\"/>"
"<value attach-x=\"7\" attach-y=\"2\" param=\"h12\"/>"
+ "<knob attach-x=\"7\" attach-y=\"3\" param=\"f8\"/>"
+ "<value attach-x=\"7\" attach-y=\"4\" param=\"f8\"/>"
"<label attach-x=\"8\" attach-y=\"0\" param=\"h16\"/>"
"<vscale attach-x=\"8\" attach-y=\"1\" param=\"h16\"/>"
"<value attach-x=\"8\" attach-y=\"2\" param=\"h16\"/>"
+ "<knob attach-x=\"8\" attach-y=\"3\" param=\"f9\"/>"
+ "<value attach-x=\"8\" attach-y=\"4\" param=\"f9\"/>"
"</table>"
"</vbox>"
;
@@ -118,6 +136,26 @@ parameter_properties organ_audio_module::param_props[] = {
{ 0, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "h12", "1 1/3'" },
{ 8, 0, 8, 80, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "h16", "1'" },
+ { 1, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f1", "Freq 1" },
+ { 3, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f2", "Freq 2" },
+ { 2, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f3", "Freq 3" },
+ { 4, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f4", "Freq 4" },
+ { 6, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f5", "Freq 5" },
+ { 8, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f6", "Freq 6" },
+ { 10, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f7", "Freq 7" },
+ { 12, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f8", "Freq 8" },
+ { 16, 1, 32, 32, PF_INT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "f9", "Freq 9" },
+
+ { 2, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w1", "Wave 1" },
+ { 2, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w2", "Wave 2" },
+ { 1, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w3", "Wave 3" },
+ { 1, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w4", "Wave 4" },
+ { 0, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w5", "Wave 5" },
+ { 0, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w6", "Wave 6" },
+ { 0, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w7", "Wave 7" },
+ { 0, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w8", "Wave 8" },
+ { 0, 0, 8, 0, PF_FLOAT | PF_SCALE_LINEAR | PF_CTL_FADER, NULL, "w9", "Wave 9" },
+
{ 1, 0, 1, 2, PF_BOOL | PF_CTL_TOGGLE, NULL, "foldover", "Foldover" },
{ 200, 10, 3000, 100, PF_FLOAT | PF_SCALE_LOG | PF_CTL_KNOB | PF_UNIT_MSEC, NULL, "perc_decay", "Perc. decay" },
{ 0.25, 0, 1, 100, PF_FLOAT | PF_SCALE_GAIN | PF_CTL_KNOB, NULL, "perc_level", "Perc. level" },
@@ -135,3 +173,28 @@ const char *rotary_speaker_speed_names[] = { "Off", "Chorale", "Tremolo", "HoldP
parameter_properties rotary_speaker_audio_module::param_props[] = {
{ 2, 0, 4, 1.01, PF_ENUM | PF_CTL_COMBO, rotary_speaker_speed_names, "vib_speed", "Speed Mode" },
};
+
+waveform_family<ORGAN_WAVE_BITS> organ_voice_base::waves[organ_voice_base::wave_count];
+
+organ_voice_base::organ_voice_base(organ_parameters *_parameters)
+: parameters(_parameters)
+{
+ note = -1;
+ static bool inited = false;
+ if (!inited)
+ {
+ float tmp[ORGAN_WAVE_SIZE];
+ bandlimiter<ORGAN_WAVE_BITS> bl;
+ inited = true;
+ for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+ tmp[i] = sin(i * 2 * M_PI / ORGAN_WAVE_SIZE);
+ waves[wave_sine].make(bl, tmp);
+ for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+ tmp[i] = (i < (ORGAN_WAVE_SIZE / 16)) ? 1 : 0;
+ normalize_waveform(tmp, ORGAN_WAVE_SIZE);
+ waves[wave_pulse].make(bl, tmp);
+ for (int i = 0; i < ORGAN_WAVE_SIZE; i++)
+ tmp[i] = i < (ORGAN_WAVE_SIZE / 4) ? sin(i * 4 * 2 * M_PI / ORGAN_WAVE_SIZE) : 0;
+ waves[wave_stretchsine].make(bl, tmp);
+ }
+}
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list