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.

237 lines
6.2KB

  1. // Copyright 2016 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. // Main synthesis voice.
  28. #ifndef PLAITS_DSP_VOICE_H_
  29. #define PLAITS_DSP_VOICE_H_
  30. #include "stmlib/stmlib.h"
  31. #include "stmlib/dsp/filter.h"
  32. #include "stmlib/dsp/limiter.h"
  33. #include "stmlib/utils/buffer_allocator.h"
  34. #include "plaits/dsp/engine/additive_engine.h"
  35. #include "plaits/dsp/engine/bass_drum_engine.h"
  36. #include "plaits/dsp/engine/chord_engine.h"
  37. #include "plaits/dsp/engine/engine.h"
  38. #include "plaits/dsp/engine/fm_engine.h"
  39. #include "plaits/dsp/engine/grain_engine.h"
  40. #include "plaits/dsp/engine/hi_hat_engine.h"
  41. #include "plaits/dsp/engine/modal_engine.h"
  42. #include "plaits/dsp/engine/noise_engine.h"
  43. #include "plaits/dsp/engine/particle_engine.h"
  44. #include "plaits/dsp/engine/snare_drum_engine.h"
  45. #include "plaits/dsp/engine/speech_engine.h"
  46. #include "plaits/dsp/engine/string_engine.h"
  47. #include "plaits/dsp/engine/swarm_engine.h"
  48. #include "plaits/dsp/engine/virtual_analog_engine.h"
  49. #include "plaits/dsp/engine/waveshaping_engine.h"
  50. #include "plaits/dsp/engine/wavetable_engine.h"
  51. #include "plaits/dsp/envelope.h"
  52. #include "plaits/dsp/fx/low_pass_gate.h"
  53. namespace plaits {
  54. const int kMaxEngines = 16;
  55. const int kMaxTriggerDelay = 8;
  56. const int kTriggerDelay = 5;
  57. class ChannelPostProcessor {
  58. public:
  59. ChannelPostProcessor() { }
  60. ~ChannelPostProcessor() { }
  61. void Init() {
  62. lpg_.Init();
  63. Reset();
  64. }
  65. void Reset() {
  66. limiter_.Init();
  67. }
  68. void Process(
  69. float gain,
  70. bool bypass_lpg,
  71. float low_pass_gate_gain,
  72. float low_pass_gate_frequency,
  73. float low_pass_gate_hf_bleed,
  74. float* in,
  75. short* out,
  76. size_t size,
  77. size_t stride) {
  78. if (gain < 0.0f) {
  79. limiter_.Process(-gain, in, size);
  80. }
  81. const float post_gain = (gain < 0.0f ? 1.0f : gain) * -32767.0f;
  82. if (!bypass_lpg) {
  83. lpg_.Process(
  84. post_gain * low_pass_gate_gain,
  85. low_pass_gate_frequency,
  86. low_pass_gate_hf_bleed,
  87. in,
  88. out,
  89. size,
  90. stride);
  91. } else {
  92. while (size--) {
  93. *out = stmlib::Clip16(1 + static_cast<int32_t>(*in++ * post_gain));
  94. out += stride;
  95. }
  96. }
  97. }
  98. private:
  99. stmlib::Limiter limiter_;
  100. LowPassGate lpg_;
  101. DISALLOW_COPY_AND_ASSIGN(ChannelPostProcessor);
  102. };
  103. struct Patch {
  104. float note;
  105. float harmonics;
  106. float timbre;
  107. float morph;
  108. float frequency_modulation_amount;
  109. float timbre_modulation_amount;
  110. float morph_modulation_amount;
  111. int engine;
  112. float decay;
  113. float lpg_colour;
  114. };
  115. struct Modulations {
  116. float engine;
  117. float note;
  118. float frequency;
  119. float harmonics;
  120. float timbre;
  121. float morph;
  122. float trigger;
  123. float level;
  124. bool frequency_patched;
  125. bool timbre_patched;
  126. bool morph_patched;
  127. bool trigger_patched;
  128. bool level_patched;
  129. };
  130. class Voice {
  131. public:
  132. Voice() { }
  133. ~Voice() { }
  134. struct Frame {
  135. short out;
  136. short aux;
  137. };
  138. void Init(stmlib::BufferAllocator* allocator);
  139. void Render(
  140. const Patch& patch,
  141. const Modulations& modulations,
  142. Frame* frames,
  143. size_t size);
  144. inline int active_engine() const { return previous_engine_index_; }
  145. private:
  146. void ComputeDecayParameters(const Patch& settings);
  147. inline float ApplyModulations(
  148. float base_value,
  149. float modulation_amount,
  150. bool use_external_modulation,
  151. float external_modulation,
  152. bool use_internal_envelope,
  153. float envelope,
  154. float default_internal_modulation,
  155. float minimum_value,
  156. float maximum_value) {
  157. float value = base_value;
  158. modulation_amount *= std::max(fabsf(modulation_amount) - 0.05f, 0.05f);
  159. modulation_amount *= 1.05f;
  160. float modulation = use_external_modulation
  161. ? external_modulation
  162. : (use_internal_envelope ? envelope : default_internal_modulation);
  163. value += modulation_amount * modulation;
  164. CONSTRAIN(value, minimum_value, maximum_value);
  165. return value;
  166. }
  167. AdditiveEngine additive_engine_;
  168. BassDrumEngine bass_drum_engine_;
  169. ChordEngine chord_engine_;
  170. FMEngine fm_engine_;
  171. GrainEngine grain_engine_;
  172. HiHatEngine hi_hat_engine_;
  173. ModalEngine modal_engine_;
  174. NoiseEngine noise_engine_;
  175. ParticleEngine particle_engine_;
  176. SnareDrumEngine snare_drum_engine_;
  177. SpeechEngine speech_engine_;
  178. StringEngine string_engine_;
  179. SwarmEngine swarm_engine_;
  180. VirtualAnalogEngine virtual_analog_engine_;
  181. WaveshapingEngine waveshaping_engine_;
  182. WavetableEngine wavetable_engine_;
  183. stmlib::HysteresisQuantizer engine_quantizer_;
  184. int previous_engine_index_;
  185. float engine_cv_;
  186. float previous_note_;
  187. bool trigger_state_;
  188. DecayEnvelope decay_envelope_;
  189. LPGEnvelope lpg_envelope_;
  190. float trigger_delay_line_[kMaxTriggerDelay];
  191. DelayLine<float, kMaxTriggerDelay> trigger_delay_;
  192. ChannelPostProcessor out_post_processor_;
  193. ChannelPostProcessor aux_post_processor_;
  194. EngineRegistry<kMaxEngines> engines_;
  195. float out_buffer_[kMaxBlockSize];
  196. float aux_buffer_[kMaxBlockSize];
  197. DISALLOW_COPY_AND_ASSIGN(Voice);
  198. };
  199. } // namespace plaits
  200. #endif // PLAITS_DSP_VOICE_H_