Make Analyzer UI require instance-access
[calf.git] / src / calf / wavetable.h
blob11d457a93279aa07e17a4a8cc586d40a2995fb54
1 #ifndef __CALF_WAVETABLE_H
2 #define __CALF_WAVETABLE_H
4 #include <assert.h>
5 #include "biquad.h"
6 #include "onepole.h"
7 #include "audio_fx.h"
8 #include "inertia.h"
9 #include "osc.h"
10 #include "synth.h"
11 #include "envelope.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);
27 slice = slice >> 8;
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;
41 phase += phasedelta;
42 return dsp::lerp(value1, value2, fracslice) * (1.0 / 8.0) * (1.0 / 32768.0);;
46 class wavetable_voice: public dsp::voice
48 public:
49 enum { Channels = 2, BlockSize = 64, MaxSampleRun = MAX_SAMPLE_RUN, EnvCount = 3, OscCount = 2 };
50 float output_buffer[BlockSize][Channels];
51 protected:
52 int note;
53 wavetable_audio_module *parent;
54 float **params;
55 dsp::decay amp;
56 wavetable_oscillator oscs[OscCount];
57 dsp::adsr envs[EnvCount];
58 /// Current MIDI velocity
59 float 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;
69 public:
70 wavetable_voice();
71 void set_params_ptr(wavetable_audio_module *_parent, int _srate);
72 void reset();
73 void note_on(int note, int vel);
74 void note_off(int /* vel */);
75 void channel_pressure(int value);
76 void steal();
77 void render_block(int current_snapshot);
78 const int16_t *get_last_table(int osc) const;
79 virtual int get_current_note() {
80 return 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;
92 };
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
96 public:
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;
102 protected:
103 uint32_t crate;
104 bool panic_flag;
106 public:
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 {
119 float pitchbend;
122 ControlSnapshot control_snapshots[MaxSnapshots];
124 public:
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);
130 return v;
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 };
138 if (panic_flag)
140 control_change(120, 0); // stop all sounds
141 control_change(121, 0); // reset all controllers
142 panic_flag = false;
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();
151 float gain = 1.0f;
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];
156 return 3;
159 void make_snapshot(int index)
161 if (index)
162 control_snapshots[index].pitchbend = inertia_pitchbend.get();
163 else
164 control_snapshots[0].pitchbend = inertia_pitchbend.get_last();
167 void set_sample_rate(uint32_t sr) {
168 setup(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;
194 #endif