1 #ifndef __CALF_WAVETABLE_H
2 #define __CALF_WAVETABLE_H
12 #include "modmatrix.h"
14 namespace calf_plugins
{
16 #define WAVETABLE_WAVE_BITS 8
18 class wavetable_audio_module
;
20 struct wavetable_oscillator
: public dsp::simple_oscillator
22 enum { SIZE
= 1 << 8, MASK
= SIZE
- 1, SCALE
= 1 << (32 - 8) };
23 int16_t (*tables
)[256];
24 inline float get(uint16_t slice
)
26 float fracslice
= (slice
& 255) * (1.0 / 256.0);
28 int16_t *waveform
= tables
[slice
];
29 int16_t *waveform2
= tables
[slice
+ 1];
30 float value1
= 0.f
, value2
= 0.f
;
31 uint32_t cphase
= phase
, cphasedelta
= phasedelta
>> 3;
32 for (int j
= 0; j
< 8; j
++)
34 uint32_t wpos
= cphase
>> (32 - 8);
35 uint32_t wpos2
= (wpos
+ 1) & MASK
;
36 float frac
= (cphase
& (SCALE
- 1)) * (1.0f
/ SCALE
);
37 value1
+= dsp::lerp((float)waveform
[wpos
], (float)waveform
[wpos2
], frac
);
38 value2
+= dsp::lerp((float)waveform2
[wpos
], (float)waveform2
[wpos2
], frac
);
39 cphase
+= cphasedelta
;
42 return dsp::lerp(value1
, value2
, fracslice
) * (1.0 / 8.0) * (1.0 / 32768.0);;
46 class wavetable_voice
: public dsp::voice
49 enum { Channels
= 2, BlockSize
= 64, MaxSampleRun
= MAX_SAMPLE_RUN
, EnvCount
= 3, OscCount
= 2 };
50 float output_buffer
[BlockSize
][Channels
];
53 wavetable_audio_module
*parent
;
56 wavetable_oscillator oscs
[OscCount
];
57 dsp::adsr envs
[EnvCount
];
58 /// Current MIDI velocity
60 /// Current calculated mod matrix outputs
61 float moddest
[wavetable_metadata::moddest_count
];
62 /// Last oscillator shift (wavetable index) of each oscillator
63 float last_oscshift
[OscCount
];
64 /// Last oscillator amplitude of each oscillator
65 float last_oscamp
[OscCount
];
66 /// Current osc amplitude
67 float cur_oscamp
[OscCount
];
68 dsp::triangle_lfo lfo1
, lfo2
;
71 void set_params_ptr(wavetable_audio_module
*_parent
, int _srate
);
73 void note_on(int note
, int vel
);
74 void note_off(int /* vel */);
75 void channel_pressure(int value
);
77 void render_block(int current_snapshot
);
78 const int16_t *get_last_table(int osc
) const;
79 virtual int get_current_note() {
82 virtual bool get_active() {
83 // printf("note %d getactive %d use_percussion %d pamp active %d\n", note, amp.get_active(), use_percussion(), pamp.get_active());
84 return (note
!= -1) && (amp
.get_active()) && !envs
[0].stopped();
86 inline void calc_derived_dests(float env0
) {
87 float cv
= dsp::clip
<float>(0.5 + 0.01 * moddest
[wavetable_metadata::moddest_oscmix
], 0.f
, 1.f
);
88 float overall
= *params
[wavetable_metadata::par_eg1toamp
] > 0 ? env0
: 1.0;
89 cur_oscamp
[0] = (1 - cv
) * *params
[wavetable_metadata::par_o1level
] * overall
;
90 cur_oscamp
[1] = (cv
) * *params
[wavetable_metadata::par_o2level
] * overall
;
94 class wavetable_audio_module
: public audio_module
<wavetable_metadata
>, public dsp::basic_synth
, public dsp::block_allvoices_base
<wavetable_voice
>, public line_graph_iface
, public mod_matrix_impl
97 using dsp::basic_synth::note_on
;
98 using dsp::basic_synth::note_off
;
99 using dsp::basic_synth::control_change
;
100 using dsp::basic_synth::pitch_bend
;
107 int16_t tables
[wt_count
][129][256]; // one dummy level for interpolation
108 /// Rows of the modulation matrix
109 dsp::modulation_entry mod_matrix_data
[mod_matrix_slots
];
110 /// Smoothed pitch bend value
111 dsp::inertia
<dsp::linear_ramp
> inertia_pitchbend
;
112 /// Smoothed channel pressure value
113 dsp::inertia
<dsp::linear_ramp
> inertia_pressure
;
114 /// Unsmoothed mod wheel value
115 float modwheel_value
;
116 wavetable_voice
*last_voice
;
118 struct ControlSnapshot
{
122 ControlSnapshot control_snapshots
[MaxSnapshots
];
125 wavetable_audio_module();
127 dsp::voice
*alloc_voice() {
128 dsp::block_voice
<wavetable_voice
> *v
= new dsp::block_voice
<wavetable_voice
>();
129 v
->set_params_ptr(this, sample_rate
);
133 uint32_t get_crate() const { return crate
; }
135 /// process function copied from Organ (will probably need some adjustments as well as implementing the panic flag elsewhere
136 uint32_t process(uint32_t offset
, uint32_t nsamples
, uint32_t inputs_mask
, uint32_t outputs_mask
) {
137 float *o
[2] = { outs
[0] + offset
, outs
[1] + offset
};
140 control_change(120, 0); // stop all sounds
141 control_change(121, 0); // reset all controllers
145 fill_snapshots(nsamples
);
146 float buf
[MAX_SAMPLE_RUN
][2];
147 dsp::zero(&buf
[0][0], 2 * nsamples
);
148 basic_synth::render_to(buf
, nsamples
);
149 if (!active_voices
.empty())
150 last_voice
= (wavetable_voice
*)*active_voices
.begin();
152 for (uint32_t i
=0; i
<nsamples
; i
++) {
153 o
[0][i
] = gain
*buf
[i
][0];
154 o
[1][i
] = gain
*buf
[i
][1];
159 void make_snapshot(int index
)
162 control_snapshots
[index
].pitchbend
= inertia_pitchbend
.get();
164 control_snapshots
[0].pitchbend
= inertia_pitchbend
.get_last();
167 void set_sample_rate(uint32_t sr
) {
169 crate
= sample_rate
/ wavetable_voice::BlockSize
;
170 inertia_pitchbend
.ramp
.set_length(crate
/ 30); // 1/30s
171 inertia_pressure
.ramp
.set_length(crate
/ 30); // 1/30s - XXXKF monosynth needs that too
173 virtual void note_on(int /*channel*/, int note
, int velocity
) { dsp::basic_synth::note_on(note
, velocity
); }
174 virtual void note_off(int /*channel*/, int note
, int velocity
) { dsp::basic_synth::note_off(note
, velocity
); }
175 virtual void control_change(int /*channel*/, int controller
, int value
);
176 /// Handle MIDI Channel Pressure
177 virtual void channel_pressure(int channel
, int value
);
178 /// Handle pitch bend message.
179 virtual void pitch_bend(int channel
, int value
)
181 inertia_pitchbend
.set_inertia((value
* *params
[par_pwhlrange
]) * (1.0 / 8192.0));
183 bool get_graph(int index
, int subindex
, int phase
, float *data
, int points
, cairo_iface
*context
, int *mode
) const;
184 bool get_layers(int index
, int generation
, unsigned int &layers
) const { layers
= LG_REALTIME_GRAPH
; return true; }
185 virtual void send_configures(send_configure_iface
*sci
) { return mod_matrix_impl::send_configures(sci
); }
186 virtual char *configure(const char *key
, const char *value
);
187 virtual const dsp::modulation_entry
*get_default_mod_matrix_value(int row
) const;