You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

284 lines
7.3KB

  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. #ifndef TIDES_GENERATOR_H_
  29. #define TIDES_GENERATOR_H_
  30. #include "stmlib/stmlib.h"
  31. #include "stmlib/algorithms/pattern_predictor.h"
  32. #include "stmlib/utils/ring_buffer.h"
  33. // #define WAVETABLE_HACK
  34. namespace tides {
  35. enum GeneratorRange {
  36. GENERATOR_RANGE_HIGH,
  37. GENERATOR_RANGE_MEDIUM,
  38. GENERATOR_RANGE_LOW
  39. };
  40. enum GeneratorMode {
  41. GENERATOR_MODE_AD,
  42. GENERATOR_MODE_LOOPING,
  43. GENERATOR_MODE_AR,
  44. };
  45. enum ControlBitMask {
  46. CONTROL_FREEZE = 1,
  47. CONTROL_GATE = 2,
  48. CONTROL_CLOCK = 4,
  49. CONTROL_CLOCK_RISING = 8,
  50. CONTROL_GATE_RISING = 16,
  51. CONTROL_GATE_FALLING = 32
  52. };
  53. enum FlagBitMask {
  54. FLAG_END_OF_ATTACK = 1,
  55. FLAG_END_OF_RELEASE = 2
  56. };
  57. struct GeneratorSample {
  58. uint16_t unipolar;
  59. int16_t bipolar;
  60. uint8_t flags;
  61. };
  62. const size_t kNumBlocks = 2;
  63. const size_t kBlockSize = 16;
  64. struct FrequencyRatio {
  65. uint32_t p;
  66. uint32_t q;
  67. };
  68. class Generator {
  69. public:
  70. Generator() { }
  71. ~Generator() { }
  72. void Init();
  73. void set_range(GeneratorRange range) {
  74. ClearFilterState();
  75. range_ = range;
  76. clock_divider_ = range_ == GENERATOR_RANGE_LOW ? 4 : 1;
  77. }
  78. void set_mode(GeneratorMode mode) {
  79. mode_ = mode;
  80. if (mode_ == GENERATOR_MODE_LOOPING) {
  81. running_ = true;
  82. }
  83. }
  84. void set_pitch(int16_t pitch) {
  85. if (sync_) {
  86. ComputeFrequencyRatio(pitch);
  87. }
  88. pitch += (12 << 7) - (60 << 7) * static_cast<int16_t>(range_);
  89. if (range_ == GENERATOR_RANGE_LOW) {
  90. pitch -= (12 << 7); // One extra octave of super LF stuff!
  91. }
  92. pitch_ = pitch;
  93. }
  94. void set_shape(int16_t shape) {
  95. shape_ = shape;
  96. }
  97. void set_slope(int16_t slope) {
  98. slope_ = slope;
  99. }
  100. void set_smoothness(int16_t smoothness) {
  101. smoothness_ = smoothness;
  102. }
  103. void set_frequency_ratio(FrequencyRatio ratio) {
  104. frequency_ratio_ = ratio;
  105. }
  106. void set_sync(bool sync) {
  107. if (!sync_ && sync) {
  108. pattern_predictor_.Init();
  109. }
  110. sync_ = sync;
  111. sync_edges_counter_ = 0;
  112. }
  113. inline GeneratorMode mode() const { return mode_; }
  114. inline GeneratorRange range() const { return range_; }
  115. inline bool sync() const { return sync_; }
  116. inline const GeneratorSample& Process(uint8_t control) {
  117. input_samples_[playback_block_][current_sample_] = control;
  118. const GeneratorSample& out = output_samples_[playback_block_][current_sample_];
  119. current_sample_ = current_sample_ + 1;
  120. if (current_sample_ >= kBlockSize) {
  121. current_sample_ = 0;
  122. playback_block_ = (playback_block_ + 1) % kNumBlocks;
  123. }
  124. return out;
  125. }
  126. inline bool writable_block() const {
  127. return render_block_ != playback_block_;
  128. }
  129. inline void Process(bool wavetableHack = false) {
  130. while (render_block_ != playback_block_) {
  131. uint8_t* in = input_samples_[render_block_];
  132. GeneratorSample* out = output_samples_[render_block_];
  133. if (!wavetableHack) {
  134. if (range_ == GENERATOR_RANGE_HIGH) {
  135. ProcessAudioRate(in, out, kBlockSize);
  136. } else {
  137. ProcessControlRate(in, out, kBlockSize);
  138. }
  139. ProcessFilterWavefolder(out, kBlockSize);
  140. }
  141. else {
  142. ProcessWavetable(in, out, kBlockSize);
  143. }
  144. render_block_ = (render_block_ + 1) % kNumBlocks;
  145. }
  146. }
  147. uint32_t clock_divider() const {
  148. return clock_divider_;
  149. }
  150. private:
  151. // There are two versions of the rendering code, one optimized for audio, with
  152. // band-limiting.
  153. void ProcessAudioRate(const uint8_t* in, GeneratorSample* out, size_t size);
  154. void ProcessControlRate(const uint8_t* in, GeneratorSample* out, size_t size);
  155. void ProcessWavetable(const uint8_t* in, GeneratorSample* out, size_t size);
  156. void ProcessFilterWavefolder(GeneratorSample* in_out, size_t size);
  157. int32_t ComputeAntialiasAttenuation(
  158. int16_t pitch,
  159. int16_t slope,
  160. int16_t shape,
  161. int16_t smoothness) const;
  162. inline void ClearFilterState() {
  163. uni_lp_state_[0] = uni_lp_state_[1] = 0;
  164. bi_lp_state_[0] = bi_lp_state_[1] = 0;
  165. }
  166. uint32_t ComputePhaseIncrement(int16_t pitch);
  167. int16_t ComputePitch(uint32_t phase_increment);
  168. int32_t ComputeCutoffFrequency(int16_t pitch, int16_t smoothness);
  169. void ComputeFrequencyRatio(int16_t pitch);
  170. inline int32_t NextIntegratedBlepSample(uint32_t t) const {
  171. if (t >= 65535) {
  172. t = 65535;
  173. }
  174. const int32_t t1 = t >> 1;
  175. const int32_t t2 = t1 * t1 >> 16;
  176. const int32_t t4 = t2 * t2 >> 16;
  177. return 12288 - t1 + (3 * t2 >> 1) - t4;
  178. }
  179. inline int32_t ThisIntegratedBlepSample(uint32_t t) const {
  180. if (t >= 65535) {
  181. t = 65535;
  182. }
  183. t = 65535 - t;
  184. const int32_t t1 = t >> 1;
  185. const int32_t t2 = t1 * t1 >> 16;
  186. const int32_t t4 = t2 * t2 >> 16;
  187. return 12288 - t1 + (3 * t2 >> 1) - t4;
  188. }
  189. GeneratorSample output_samples_[kNumBlocks][kBlockSize];
  190. uint8_t input_samples_[kNumBlocks][kBlockSize];
  191. size_t current_sample_;
  192. volatile size_t playback_block_;
  193. volatile size_t render_block_;
  194. GeneratorMode mode_;
  195. GeneratorRange range_;
  196. GeneratorSample previous_sample_;
  197. GeneratorSample buffer_[kBlockSize];
  198. uint32_t clock_divider_;
  199. uint16_t prescaler_;
  200. int16_t pitch_;
  201. int16_t previous_pitch_;
  202. int16_t shape_;
  203. int16_t slope_;
  204. int32_t smoothed_slope_;
  205. int16_t smoothness_;
  206. int16_t attenuation_;
  207. uint32_t phase_;
  208. uint32_t phase_increment_;
  209. uint16_t x_;
  210. uint16_t y_;
  211. uint16_t z_;
  212. bool wrap_;
  213. bool sync_;
  214. FrequencyRatio frequency_ratio_;
  215. // Time measurement and clock divider for PLL mode.
  216. uint32_t sync_counter_;
  217. uint32_t sync_edges_counter_;
  218. uint32_t local_osc_phase_;
  219. uint32_t local_osc_phase_increment_;
  220. uint32_t target_phase_increment_;
  221. uint32_t eor_counter_;
  222. stmlib::PatternPredictor<32, 8> pattern_predictor_;
  223. int64_t uni_lp_state_[2];
  224. int64_t bi_lp_state_[2];
  225. bool running_;
  226. // Polyblep status.
  227. int32_t next_sample_;
  228. bool slope_up_;
  229. uint32_t mid_point_;
  230. static const FrequencyRatio frequency_ratios_[];
  231. static const int16_t num_frequency_ratios_;
  232. DISALLOW_COPY_AND_ASSIGN(Generator);
  233. };
  234. } // namespace tides
  235. #endif // TIDES_GENERATOR_H_