1 // Copyright 2013 Olivier Gillet.
2 //
3 // Author: Olivier Gillet (ol.gillet@gmail.com)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // THE SOFTWARE.
22 //
23 // See http://creativecommons.org/licenses/MIT/ for more information.
24 //
25 // -----------------------------------------------------------------------------
26 //
27 // Tidal generator.
28 
29 #ifndef TIDES_GENERATOR_H_
30 #define TIDES_GENERATOR_H_
31 
32 #include "stmlib/stmlib.h"
33 
34 #include "stmlib/algorithms/pattern_predictor.h"
35 #include "stmlib/utils/ring_buffer.h"
36 
37 // #define WAVETABLE_HACK
38 
39 namespace tides {
40 
41 enum GeneratorRange {
42   GENERATOR_RANGE_HIGH,
43   GENERATOR_RANGE_MEDIUM,
44   GENERATOR_RANGE_LOW
45 };
46 
47 enum GeneratorMode {
48   GENERATOR_MODE_AD,
49   GENERATOR_MODE_LOOPING,
50   GENERATOR_MODE_AR,
51 };
52 
53 enum ControlBitMask {
54   CONTROL_FREEZE = 1,
55   CONTROL_GATE = 2,
56   CONTROL_CLOCK = 4,
57   CONTROL_CLOCK_RISING = 8,
58   CONTROL_GATE_RISING = 16,
59   CONTROL_GATE_FALLING = 32
60 };
61 
62 enum FlagBitMask {
63   FLAG_END_OF_ATTACK = 1,
64   FLAG_END_OF_RELEASE = 2
65 };
66 
67 struct GeneratorSample {
68   uint16_t unipolar;
69   int16_t bipolar;
70   uint8_t flags;
71 };
72 
73 const uint16_t kBlockSize = 16;
74 
75 struct FrequencyRatio {
76   uint32_t p;
77   uint32_t q;
78 };
79 
80 class Generator {
81  public:
Generator()82   Generator() { }
~Generator()83   ~Generator() { }
84 
85   void Init();
86 
set_range(GeneratorRange range)87   void set_range(GeneratorRange range) {
88     ClearFilterState();
89     range_ = range;
90     clock_divider_ =
91       /* harmonic oscillator is sampled at 24kHz */
92       feature_mode_ == FEAT_MODE_HARMONIC ? 2 :
93       range_ == GENERATOR_RANGE_LOW ? 4 : 1;
94   }
95 
set_mode(GeneratorMode mode)96   void set_mode(GeneratorMode mode) {
97     mode_ = mode;
98     if (mode_ == GENERATOR_MODE_LOOPING) {
99       running_ = true;
100     }
101   }
102 
set_pitch_high_range(int16_t pitch,int16_t fm)103   void set_pitch_high_range(int16_t pitch, int16_t fm) {
104     if (sync_) {
105       ComputeFrequencyRatio(pitch);
106     }
107     pitch_ = pitch + (12 << 7) + fm;
108   }
109 
set_pitch(int16_t pitch,int16_t fm)110   void set_pitch(int16_t pitch, int16_t fm) {
111     if (sync_) {
112       ComputeFrequencyRatio(pitch);
113     }
114 
115     pitch += (12 << 7) - (60 << 7) * static_cast<int16_t>(range_);
116     if (range_ == GENERATOR_RANGE_LOW) {
117       pitch -= (12 << 7);  // One extra octave of super LF stuff!
118     }
119     pitch_ = pitch + fm;
120   }
121 
set_shape(int16_t shape)122   void set_shape(int16_t shape) {
123     shape_ = shape;
124   }
125 
set_slope(int16_t slope)126   void set_slope(int16_t slope) {
127 #ifndef WAVETABLE_HACK
128     if (range_ == GENERATOR_RANGE_HIGH &&
129         feature_mode_ != FEAT_MODE_HARMONIC) {
130       CONSTRAIN(slope, -32512, 32512);
131     }
132 #endif  // WAVETABLE_HACK
133     slope_ = slope;
134   }
135 
set_smoothness(int16_t smoothness)136   void set_smoothness(int16_t smoothness) {
137     smoothness_ = smoothness;
138   }
139 
set_frequency_ratio(FrequencyRatio ratio)140   void set_frequency_ratio(FrequencyRatio ratio) {
141     frequency_ratio_ = ratio;
142   }
143 
set_waveshaper_antialiasing(bool antialiasing)144   void set_waveshaper_antialiasing(bool antialiasing) {
145     antialiasing_ = antialiasing;
146   }
147 
set_sync(bool sync)148   void set_sync(bool sync) {
149     if (!sync_ && sync) {
150       pattern_predictor_.Init();
151     }
152     sync_ = sync;
153     sync_edges_counter_ = 0;
154   }
155 
set_pulse_width(uint16_t pw)156   void set_pulse_width(uint16_t pw) {
157     pulse_width_ = pw;
158   }
159 
mode()160   inline GeneratorMode mode() const { return mode_; }
range()161   inline GeneratorRange range() const { return range_; }
sync()162   inline bool sync() const { return sync_; }
163 
Process(uint8_t control)164   inline GeneratorSample Process(uint8_t control) {
165     input_buffer_.Overwrite(control);
166     return output_buffer_.ImmediateRead();
167   }
168 
writable_block()169   inline bool writable_block() const {
170     return output_buffer_.writable() >= kBlockSize;
171   }
172 
FillBufferSafe()173   inline bool FillBufferSafe() {
174     if (!writable_block()) {
175       return false;
176     } else {
177       FillBuffer();
178       return true;
179     }
180   }
181 
182   void FillBuffer();
183 
clock_divider()184   uint32_t clock_divider() const {
185     return clock_divider_;
186   }
187 
188   enum FeatureMode {
189     FEAT_MODE_FUNCTION,
190     FEAT_MODE_HARMONIC,
191     FEAT_MODE_RANDOM,
192   };
193 
194   FeatureMode feature_mode_;
195 
196  private:
197   // There are two versions of the rendering code, one optimized for audio, with
198   // band-limiting.
199   void FillBufferAudioRate();
200   void FillBufferControlRate();
201   void FillBufferWavetable();
202   template<GeneratorMode mode> void FillBufferHarmonic();
203   void FillBufferRandom();
204   int32_t ComputeAntialiasAttenuation(
205         int16_t pitch,
206         int16_t slope,
207         int16_t shape,
208         int16_t smoothness);
209 
ClearFilterState()210   inline void ClearFilterState() {
211     uni_lp_state_[0] = uni_lp_state_[1] = 0;
212     bi_lp_state_[0] = bi_lp_state_[1] = 0;
213   }
214 
215   int32_t ComputePhaseIncrement(int16_t pitch);
216   int16_t ComputePitch(int32_t phase_increment);
217   int32_t ComputeCutoffFrequency(int16_t pitch, int16_t smoothness);
218   void ComputeFrequencyRatio(int16_t pitch);
219 
220   stmlib::RingBuffer<uint8_t, kBlockSize * 2> input_buffer_;
221   stmlib::RingBuffer<GeneratorSample, kBlockSize * 2> output_buffer_;
222 
223   GeneratorMode mode_;
224   GeneratorRange range_;
225   GeneratorSample previous_sample_;
226 
227   uint32_t clock_divider_;
228 
229   int16_t pitch_;
230   int16_t previous_pitch_;
231   int16_t shape_;
232   int16_t slope_;
233   int32_t smoothed_slope_;
234   int16_t smoothness_;
235   bool antialiasing_;
236   uint16_t final_gain_;
237 
238   uint32_t phase_;
239   int32_t phase_increment_;
240   uint32_t sub_phase_;
241   uint16_t x_;
242   uint16_t y_;
243   uint16_t z_;
244   bool wrap_;
245 
246   uint16_t pulse_width_;
247   uint32_t divided_phase_;
248   uint32_t divider_;
249   uint32_t divider_counter_;
250   uint32_t delayed_phase_;
251   int32_t delayed_phase_increment_;
252   uint32_t delay_;
253   uint32_t delay_counter_;
254   int16_t previous_slope_;
255   uint32_t delayed_threshold_;
256 
257   uint16_t current_value_[2];
258   uint16_t next_value_[2];
259   bool walk_direction_[2];
260   uint16_t value_[2];
261 
262   int16_t old_slope_;
263   int16_t old_pitch_;
264 
265   bool sync_;
266   FrequencyRatio frequency_ratio_;
267 
268   // Time measurement and clock divider for PLL mode.
269   uint32_t sync_counter_;
270   uint32_t sync_edges_counter_;
271   uint32_t local_osc_phase_;
272   int32_t local_osc_phase_increment_;
273   int32_t target_phase_increment_;
274   uint32_t eor_counter_;
275 
276   stmlib::PatternPredictor<32, 8> pattern_predictor_;
277 
278   int64_t uni_lp_state_[2];
279   int64_t bi_lp_state_[2];
280 
281   bool running_;
282   bool previous_freeze_;
283   bool previous_clock_;
284 
285   static const FrequencyRatio frequency_ratios_[];
286   static const int16_t num_frequency_ratios_;
287 
288   static const uint8_t kNumHarmonics = 16;
289   static const uint8_t kNumHarmonicsPowers = 12;
290 
291   uint16_t envelope_[kNumHarmonics];
292   uint16_t envelope_increment_[kNumHarmonics];
293   uint8_t harm_permut_[kNumHarmonics];
294 
295   void RandomizeDelay();
296   void RandomizeDivider();
297   void RandomizeHarmonicPhase();
298   void RandomizeHarmonicDistribution();
299 
300   DISALLOW_COPY_AND_ASSIGN(Generator);
301 };
302 
303 }  // namespace tides
304 
305 #endif  // TIDES_GENERATOR_H_
306