[SCM] calf/master: + Organ: polyphonic percussion mode (ugly ugly code)
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:37:28 UTC 2013
The following commit has been merged in the master branch:
commit 2127eb94d39512415feed4e7bc7fc63db06e7e6f
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date: Mon Aug 4 19:37:45 2008 +0000
+ Organ: polyphonic percussion mode (ugly ugly code)
git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@255 78b06b96-2940-0410-b7fc-879d825d01d8
diff --git a/src/calf/organ.h b/src/calf/organ.h
index da9d412..4b6696b 100644
--- a/src/calf/organ.h
+++ b/src/calf/organ.h
@@ -148,10 +148,13 @@ public:
perctrig_first = 0,
perctrig_each,
perctrig_eachplus,
+ perctrig_polyphonic,
perctrig_count
};
typedef waveform_family<ORGAN_WAVE_BITS> small_wave_family;
typedef waveform_family<ORGAN_BIG_WAVE_BITS> big_wave_family;
+public:
+ organ_parameters *parameters;
protected:
static small_wave_family (*waves)[wave_count_small];
static big_wave_family (*big_waves)[wave_count_big];
@@ -159,8 +162,16 @@ protected:
// dsp::sine_table<float, ORGAN_WAVE_SIZE, 1> sine_wave;
int note;
dsp::decay amp;
+ /// percussion FM carrier amplitude envelope
+ dsp::decay pamp;
+ /// percussion FM modulator amplitude envelope
+ dsp::decay fm_amp;
+ dsp::fixed_point<int64_t, 20> pphase, dpphase;
+ dsp::fixed_point<int64_t, 20> modphase, moddphase;
+ float fm_keytrack;
+ int &sample_rate_ref;
- organ_voice_base(organ_parameters *_parameters);
+ organ_voice_base(organ_parameters *_parameters, int &_sample_rate_ref);
inline float wave(float *data, dsp::fixed_point<int, 20> ph) {
return ph.lerp_table_lookup_float(data);
@@ -170,7 +181,6 @@ protected:
return ph.lerp_table_lookup_float_mask(data, ORGAN_BIG_WAVE_SIZE - 1);
}
public:
- organ_parameters *parameters;
static inline small_wave_family &get_wave(int wave) {
return (*waves)[wave];
}
@@ -178,6 +188,23 @@ public:
return (*big_waves)[wave];
}
static void precalculate_waves();
+ void update_pitch()
+ {
+ float phase = synth::midi_note_to_phase(note, 100 * parameters->global_transpose + parameters->global_detune, sample_rate_ref);
+ dpphase.set(phase * parameters->percussion_harmonic * parameters->pitch_bend);
+ moddphase.set(phase * parameters->percussion_fm_harmonic * parameters->pitch_bend);
+ }
+ // this doesn't really have a voice interface
+ void render_percussion_to(float (*buf)[2], int nsamples);
+ void perc_note_on(int note, int vel);
+ void perc_reset()
+ {
+ pphase = 0;
+ modphase = 0;
+ dpphase = 0;
+ moddphase = 0;
+ note = -1;
+ }
};
class organ_vibrato
@@ -209,7 +236,7 @@ protected:
public:
organ_voice()
- : organ_voice_base(NULL),
+ : organ_voice_base(NULL, sample_rate),
expression(linear_ramp(16)) {
}
@@ -237,6 +264,7 @@ public:
velocity = vel * 1.0 / 127.0;
amp.set(1.0f);
released = false;
+ perc_note_on(note, vel);
}
void note_off(int /* vel */) {
@@ -250,48 +278,30 @@ public:
return note;
}
virtual bool get_active() {
- return (note != -1) && amp.get_active();
+ return (note != -1) && (amp.get_active() || (use_percussion() && pamp.get_active()));
}
void update_pitch();
+ inline bool use_percussion()
+ {
+ return dsp::fastf2i_drm(parameters->percussion_trigger) == perctrig_polyphonic;
+ }
};
/// Not a true voice, just something with similar-ish interface.
class percussion_voice: public organ_voice_base {
public:
int sample_rate;
- dsp::fixed_point<int64_t, 20> phase, modphase, dphase, moddphase;
- dsp::decay fm_amp;
- float fm_keytrack;
percussion_voice(organ_parameters *_parameters)
- : organ_voice_base(_parameters)
+ : organ_voice_base(_parameters, sample_rate)
{
}
- void reset() {
- phase = 0;
- modphase = 0;
- dphase = 0;
- moddphase = 0;
- note = -1;
- }
-
- void note_on(int note, int vel);
-
- void update_pitch()
- {
- float phase = synth::midi_note_to_phase(note, 0, sample_rate);
- dphase.set(phase * parameters->percussion_harmonic * parameters->pitch_bend);
- moddphase.set(phase * parameters->percussion_fm_harmonic * parameters->pitch_bend);
- }
-
- // this doesn't really have a voice interface
- void render_to(float (*buf)[2], int nsamples);
bool get_active() {
- return (note != -1) && amp.get_active();
+ return (note != -1) && pamp.get_active();
}
bool get_noticable() {
- return (note != -1) && (amp.get() > 0.2);
+ return (note != -1) && (pamp.get() > 0.2 * parameters->percussion_level);
}
void setup(int sr) {
sample_rate = sr;
@@ -343,7 +353,7 @@ struct drawbar_organ: public synth::basic_synth {
global_vibrato.process(parameters, buf + i, min(64, nsamples - i), sample_rate);
}
if (percussion.get_active())
- percussion.render_to(buf, nsamples);
+ percussion.render_percussion_to(buf, nsamples);
float gain = parameters->master * (1.0 / (9 * 8));
for (int i=0; i<nsamples; i++) {
output[0][i] = gain*buf[i][0];
@@ -356,7 +366,7 @@ struct drawbar_organ: public synth::basic_synth {
return v;
}
virtual void percussion_note_on(int note, int vel) {
- percussion.note_on(note, vel);
+ percussion.perc_note_on(note, vel);
}
virtual void params_changed() = 0;
virtual void setup(int sr) {
@@ -386,6 +396,8 @@ struct drawbar_organ: public synth::basic_synth {
return true;
case organ_voice_base::perctrig_eachplus:
return !percussion.get_noticable();
+ case organ_voice_base::perctrig_polyphonic:
+ return false;
}
}
};
diff --git a/src/organ.cpp b/src/organ.cpp
index e5e7509..b36465f 100644
--- a/src/organ.cpp
+++ b/src/organ.cpp
@@ -417,7 +417,7 @@ bool organ_audio_module::get_graph(int index, int subindex, float *data, int poi
const char *organ_audio_module::port_names[] = {"Out L", "Out R"};
-const char *organ_percussion_trigger_names[] = { "First note", "Each note", "Each, no retrig" };
+const char *organ_percussion_trigger_names[] = { "First note", "Each note", "Each, no retrig", "Polyphonic" };
const char *organ_wave_names[] = {
"Sin",
@@ -927,12 +927,56 @@ void organ_voice_base::precalculate_waves()
}
}
-organ_voice_base::organ_voice_base(organ_parameters *_parameters)
+organ_voice_base::organ_voice_base(organ_parameters *_parameters, int &_sample_rate_ref)
: parameters(_parameters)
+, sample_rate_ref(_sample_rate_ref)
{
note = -1;
}
+void organ_voice_base::render_percussion_to(float (*buf)[2], int nsamples)
+{
+ if (note == -1)
+ return;
+
+ if (!pamp.get_active())
+ return;
+ if (parameters->percussion_level < small_value<float>())
+ return;
+ float level = parameters->percussion_level * 9;
+ static float zeros[ORGAN_WAVE_SIZE];
+ // XXXKF the decay needs work!
+ double age_const = parameters->perc_decay_const;
+ double fm_age_const = parameters->perc_fm_decay_const;
+ int timbre = parameters->get_percussion_wave();
+ if (timbre < 0 || timbre >= wave_count_small)
+ return;
+ int timbre2 = parameters->get_percussion_fm_wave();
+ if (timbre2 < 0 || timbre2 >= wave_count_small)
+ timbre2 = wave_sine;
+ float *fmdata = (*waves)[timbre2].get_level(moddphase.get());
+ if (!fmdata)
+ fmdata = zeros;
+ float *data = (*waves)[timbre].get_level(dpphase.get());
+ if (!data) {
+ pamp.set(0.0);
+ return;
+ }
+ float s = parameters->percussion_stereo * ORGAN_WAVE_SIZE * (0.5 / 360.0);
+ for (int i = 0; i < nsamples; i++) {
+ float fm = wave(fmdata, modphase);
+ fm *= ORGAN_WAVE_SIZE * parameters->percussion_fm_depth * fm_amp.get();
+ modphase += moddphase;
+ fm_amp.age_exp(fm_age_const, 1.0 / 32768.0);
+
+ float lamp = level * pamp.get();
+ buf[i][0] += lamp * wave(data, pphase + dsp::fixed_point<int64_t, 52>(fm - s));
+ buf[i][1] += lamp * wave(data, pphase + dsp::fixed_point<int64_t, 52>(fm + s));
+ pamp.age_exp(age_const, 1.0 / 32768.0);
+ pphase += dpphase;
+ }
+}
+
void organ_vibrato::reset()
{
for (int i = 0; i < VibratoSize; i++)
@@ -975,6 +1019,7 @@ void organ_vibrato::process(organ_parameters *parameters, float (*data)[2], unsi
void organ_voice::update_pitch()
{
+ organ_voice_base::update_pitch();
dphase.set(synth::midi_note_to_phase(note, 100 * parameters->global_transpose + parameters->global_detune, sample_rate) * parameters->pitch_bend);
}
@@ -985,7 +1030,11 @@ void organ_voice::render_block() {
dsp::zero(&output_buffer[0][0], Channels * BlockSize);
dsp::zero(&aux_buffers[1][0][0], 2 * Channels * BlockSize);
if (!amp.get_active())
+ {
+ if (use_percussion())
+ render_percussion_to(output_buffer, BlockSize);
return;
+ }
update_pitch();
dsp::fixed_point<int, 20> tphase, tdphase;
@@ -1130,6 +1179,9 @@ void organ_voice::render_block() {
amp.age_lin((1.0/44100.0)/0.03,0.0);
}
}
+
+ if (use_percussion())
+ render_percussion_to(output_buffer, BlockSize);
}
void drawbar_organ::update_params()
@@ -1166,16 +1218,15 @@ void organ_audio_module::execute(int cmd_no)
}
}
-void percussion_voice::note_on(int note, int vel)
+void organ_voice_base::perc_note_on(int note, int vel)
{
// do not reset phase if voice is still running (to prevent clicks, even at cost of slight loss of "percussiveness")
- if (!amp.get_active())
+ if (!pamp.get_active())
{
- phase = 0;
- modphase = 0;
+ perc_reset();
}
this->note = note;
- amp.set(1.0f + (vel - 127) * parameters->percussion_vel2amp / 127.0);
+ pamp.set(1.0f + (vel - 127) * parameters->percussion_vel2amp / 127.0);
update_pitch();
float (*kt)[2] = parameters->percussion_keytrack;
// assume last point (will be put there by padding)
@@ -1193,49 +1244,6 @@ void percussion_voice::note_on(int note, int vel)
fm_amp.set(fm_keytrack * (1.0f + (vel - 127) * parameters->percussion_vel2fm / 127.0));
}
-void percussion_voice::render_to(float (*buf)[2], int nsamples)
-{
- if (note == -1)
- return;
-
- if (!amp.get_active())
- return;
- if (parameters->percussion_level < small_value<float>())
- return;
- float level = parameters->percussion_level * 9;
- static float zeros[ORGAN_WAVE_SIZE];
- // XXXKF the decay needs work!
- double age_const = parameters->perc_decay_const;
- double fm_age_const = parameters->perc_fm_decay_const;
- int timbre = parameters->get_percussion_wave();
- if (timbre < 0 || timbre >= wave_count_small)
- return;
- int timbre2 = parameters->get_percussion_fm_wave();
- if (timbre2 < 0 || timbre2 >= wave_count_small)
- timbre2 = wave_sine;
- float *fmdata = (*waves)[timbre2].get_level(moddphase.get());
- if (!fmdata)
- fmdata = zeros;
- float *data = (*waves)[timbre].get_level(dphase.get());
- if (!data) {
- amp.set(0.0);
- return;
- }
- float s = parameters->percussion_stereo * ORGAN_WAVE_SIZE * (0.5 / 360.0);
- for (int i = 0; i < nsamples; i++) {
- float fm = wave(fmdata, modphase);
- fm *= ORGAN_WAVE_SIZE * parameters->percussion_fm_depth * fm_amp.get();
- modphase += moddphase;
- fm_amp.age_exp(fm_age_const, 1.0 / 32768.0);
-
- float lamp = level * amp.get();
- buf[i][0] += lamp * wave(data, phase + dsp::fixed_point<int64_t, 20>(fm - s));
- buf[i][1] += lamp * wave(data, phase + dsp::fixed_point<int64_t, 20>(fm + s));
- amp.age_exp(age_const, 1.0 / 32768.0);
- phase += dphase;
- }
-}
-
char *organ_audio_module::configure(const char *key, const char *value)
{
if (!strcmp(key, "map_curve"))
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list