[SCM] calf/master: + Synth framework: add a block_voice class template, which can be used for synths that generate audio in constant-size blocks + Organ: refactor to use block_voice for sound generation
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:37:06 UTC 2013
The following commit has been merged in the master branch:
commit 94f9c2157d8a2fca85ad9a8702b71fee386f0eea
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date: Thu Apr 3 19:53:13 2008 +0000
+ Synth framework: add a block_voice class template, which can be used for synths that generate audio in constant-size blocks
+ Organ: refactor to use block_voice for sound generation
git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@142 78b06b96-2940-0410-b7fc-879d825d01d8
diff --git a/src/calf/organ.h b/src/calf/organ.h
index 026553c..bba3267 100644
--- a/src/calf/organ.h
+++ b/src/calf/organ.h
@@ -27,6 +27,13 @@
namespace synth
{
+struct organproc_parameters
+{
+ float cutoff;
+ float resonance;
+ float attack, decay, sustain, release;
+};
+
struct organ_parameters {
float drawbars[9];
float harmonics[9];
@@ -40,6 +47,8 @@ struct organ_parameters {
float percussion_harmonic;
float master;
+ organproc_parameters procs[2];
+
double perc_decay_const;
float multiplier[9];
int phaseshift[9];
@@ -59,25 +68,26 @@ protected:
// dsp::sine_table<float, ORGAN_WAVE_SIZE, 1> sine_wave;
int note;
dsp::decay amp;
- organ_parameters *parameters;
organ_voice_base(organ_parameters *_parameters);
inline float wave(float *data, dsp::fixed_point<int, 20> ph) {
return ph.lerp_table_lookup_float(data);
}
+public:
+ organ_parameters *parameters;
};
class organ_voice: public synth::voice, public organ_voice_base {
protected:
+ enum { Channels = 2, BlockSize = 32 };
+ float output_buffer[BlockSize][Channels];
bool released;
- int h4, h6, h8, h12, h16;
- dsp::fixed_point<int, 3> h10;
dsp::fixed_point<int64_t, 52> phase, dphase;
public:
- organ_voice(organ_parameters *_parameters)
- : organ_voice_base(_parameters) {
+ organ_voice()
+ : organ_voice_base(NULL) {
}
void reset() {
@@ -90,85 +100,57 @@ public:
dphase.set(synth::midi_note_to_phase(note, 0, sample_rate));
amp.set(1.0f);
released = false;
- calc_foldover();
}
void note_off(int /* vel */) {
released = true;
}
- void calc_foldover() {
- h4 = 4, h6 = 6, h8 = 8, h10 = 10, h12 = 12, h16 = 16;
- if (!parameters->get_foldover()) return;
- const int foc = 120, foc2 = 120 + 12, foc3 = 120 + 24;
- if (note + 24 >= foc) h4 = 2;
- if (note + 24 >= foc2) h4 = 1;
- if (note + 36 >= foc) h8 = 4;
- if (note + 36 >= foc2) h8 = 2;
- if (note + 40 >= foc) h10 = 5.0;
- if (note + 40 >= foc2) h10 = 2.5;
- if (note + 43 >= foc) h12 = 6;
- if (note + 43 >= foc2) h12 = 3;
- if (note + 48 >= foc) h16 = 8;
- if (note + 48 >= foc2) h16 = 4;
- if (note + 48 >= foc3) h16 = 2;
-// printf("h= %d %d %d %f %d %d\n", h4, h6, h8, (float)h10, h12, h16);
- }
-
- void render_to(float *buf[2], int nsamples) {
+ void render_block() {
if (note == -1)
return;
- if (!amp.get_active()) {
- dsp::zero(buf[0], nsamples);
- dsp::zero(buf[1], nsamples);
- } else {
- float tmp[2][256], *sigl, *sigr;
- if (released)
+ dsp::zero(&output_buffer[0][0], 2 * BlockSize);
+ if (!amp.get_active())
+ return;
+
+ dsp::fixed_point<int, 20> tphase, tdphase;
+ for (int h = 0; h < 9; h++)
+ {
+ float amp = parameters->drawbars[h];
+ if (amp < small_value<float>())
+ continue;
+ float *data;
+ dsp::fixed_point<int, 24> hm = dsp::fixed_point<int, 24>(parameters->multiplier[h]);
+ int waveid = (int)parameters->waveforms[h];
+ if (waveid < 0 || waveid >= wave_count)
+ waveid = 0;
+ for (int i = 0; i < 4; i++)
{
- sigl = tmp[0];
- sigr = tmp[1];
- for (int i=0; i<nsamples; i++)
- tmp[0][i] = tmp[1][i] = 0;
+ data = waves[waveid].get_level((dphase * hm).get() >> i);
+ if (data)
+ break;
}
- else {
- sigl = buf[0];
- sigr = buf[1];
- }
- 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->multiplier[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.set(((phase * hm).get() & 0xFFFFFFFF) + parameters->phaseshift[h]);
- tdphase.set((dphase * hm).get() & 0xFFFFFFFF);
- float amp = parameters->drawbars[h];
- float ampl = amp * 0.5f * (-1 + parameters->pan[h]);
- float ampr = amp * 0.5f * (1 + parameters->pan[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);
- sigl[i] += wave(data, tphase)*ampl;
- sigr[i] += wave(data, tphase)*ampr;
- tphase += tdphase;
- }
+ if (!data)
+ continue;
+ tphase.set(((phase * hm).get() & 0xFFFFFFFF) + parameters->phaseshift[h]);
+ tdphase.set((dphase * hm).get() & 0xFFFFFFFF);
+ float ampl = amp * 0.5f * (-1 + parameters->pan[h]);
+ float ampr = amp * 0.5f * (1 + parameters->pan[h]);
+ for (int i=0; i < (int)BlockSize; i++) {
+ float wv = wave(data, tphase);
+ output_buffer[i][0] += wv * ampl;
+ output_buffer[i][1] += wv * ampr;
+ tphase += tdphase;
}
- phase += dphase * nsamples;
- if (released)
- {
- for (int i=0; i<nsamples; i++) {
- buf[0][i] += tmp[0][i] * amp.get();
- buf[1][i] += tmp[1][i] * amp.get();
- amp.age_lin((1.0/44100.0)/0.03,0.0);
- }
+ }
+ phase += dphase * BlockSize;
+ if (released)
+ {
+ for (int i=0; i < (int) BlockSize; i++) {
+ output_buffer[i][0] *= amp.get();
+ output_buffer[i][1] *= amp.get();
+ amp.age_lin((1.0/44100.0)/0.03,0.0);
}
}
}
@@ -190,6 +172,7 @@ public:
: organ_voice_base(_parameters)
{
}
+
void reset() {
phase = 0;
note = -1;
@@ -256,7 +239,9 @@ struct drawbar_organ: public synth::basic_synth {
}
}
synth::voice *alloc_voice() {
- return new organ_voice(parameters);
+ block_voice<organ_voice> *v = new block_voice<organ_voice>();
+ v->parameters = parameters;
+ return v;
}
virtual void first_note_on(int note, int vel) {
percussion.note_on(note, vel);
diff --git a/src/calf/synth.h b/src/calf/synth.h
index fd2dee0..ab1c49c 100644
--- a/src/calf/synth.h
+++ b/src/calf/synth.h
@@ -125,6 +125,55 @@ public:
virtual ~voice() {}
};
+/// An "optimized" voice class using fixed-size processing units
+/// and fixed number of channels. The drawback is that voice
+/// control is not sample-accurate, and no modulation input
+/// is possible, but it should be good enough for most cases
+/// (like Calf Organ).
+template<class Base>
+class block_voice: public Base {
+public:
+ // derived from Base
+ // enum { Channels = 2 };
+ using Base::Channels;
+ // enum { BlockSize = 16 };
+ using Base::BlockSize;
+ // float output_buffer[BlockSize][Channels];
+ using Base::output_buffer;
+ // void render_block();
+ using Base::render_block;
+ unsigned int read_ptr;
+
+ block_voice()
+ {
+ read_ptr = BlockSize;
+ }
+ virtual void reset()
+ {
+ Base::reset();
+ read_ptr = BlockSize;
+ }
+ virtual void render_to(float *buf[], int nsamples)
+ {
+ int p = 0;
+ while(p < nsamples)
+ {
+ if (read_ptr == BlockSize)
+ {
+ render_block();
+ read_ptr = 0;
+ }
+ int ncopy = std::min<int>(BlockSize - read_ptr, nsamples - p);
+ for (int i = 0; i < ncopy; i++)
+ for (int c = 0; c < Channels; c++)
+ buf[c][p + i] += output_buffer[read_ptr + i][c];
+ p += ncopy;
+ read_ptr += ncopy;
+ }
+ }
+
+};
+
/// Base class for all kinds of polyphonic instruments, provides
/// somewhat reasonable voice management, pedal support - and
/// little else. It's implemented as a base class with virtual
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list