1 // Copyright 2013 Emilie Gillet. 2 // 3 // Author: Emilie Gillet (emilie.o.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 // Voice. 28 29 #ifndef YARNS_VOICE_H_ 30 #define YARNS_VOICE_H_ 31 32 #include "stmlib/stmlib.h" 33 #include "stmlib/utils/ring_buffer.h" 34 35 namespace yarns { 36 37 const uint16_t kNumOctaves = 11; 38 const size_t kAudioBlockSize = 64; 39 40 enum TriggerShape { 41 TRIGGER_SHAPE_SQUARE, 42 TRIGGER_SHAPE_LINEAR, 43 TRIGGER_SHAPE_EXPONENTIAL, 44 TRIGGER_SHAPE_RING, 45 TRIGGER_SHAPE_STEPS, 46 TRIGGER_SHAPE_NOISE_BURST 47 }; 48 49 enum AudioMode { 50 AUDIO_MODE_OFF, 51 AUDIO_MODE_SAW, 52 AUDIO_MODE_SQUARE, 53 AUDIO_MODE_TRIANGLE, 54 AUDIO_MODE_SINE 55 }; 56 57 class Oscillator { 58 public: Oscillator()59 Oscillator() { } ~Oscillator()60 ~Oscillator() { } 61 void Init(int32_t scale, int32_t offset); 62 void Render(uint8_t mode, int16_t note, bool gate); ReadSample()63 inline uint16_t ReadSample() { 64 return audio_buffer_.ImmediateRead(); 65 } 66 67 private: 68 uint32_t ComputePhaseIncrement(int16_t pitch); 69 70 void RenderSilence(); 71 void RenderNoise(); 72 void RenderSine(uint32_t phase_increment); 73 void RenderSaw(uint32_t phase_increment); 74 void RenderSquare(uint32_t phase_increment, uint32_t pw, bool integrate); 75 ThisBlepSample(uint32_t t)76 inline int32_t ThisBlepSample(uint32_t t) { 77 if (t > 65535) { 78 t = 65535; 79 } 80 return t * t >> 18; 81 } 82 NextBlepSample(uint32_t t)83 inline int32_t NextBlepSample(uint32_t t) { 84 if (t > 65535) { 85 t = 65535; 86 } 87 t = 65535 - t; 88 return -static_cast<int32_t>(t * t >> 18); 89 } 90 91 int32_t scale_; 92 int32_t offset_; 93 uint32_t phase_; 94 int32_t next_sample_; 95 int32_t integrator_state_; 96 bool high_; 97 stmlib::RingBuffer<uint16_t, kAudioBlockSize * 2> audio_buffer_; 98 99 DISALLOW_COPY_AND_ASSIGN(Oscillator); 100 }; 101 102 class Voice { 103 public: Voice()104 Voice() { } ~Voice()105 ~Voice() { } 106 107 void Init(bool reset_calibration); 108 void ResetAllControllers(); 109 110 void Calibrate(uint16_t* calibrated_dac_code); 111 void Refresh(); 112 void NoteOn(int16_t note, uint8_t velocity, uint8_t portamento, bool trigger); 113 void NoteOff(); 114 void ControlChange(uint8_t controller, uint8_t value); PitchBend(uint16_t pitch_bend)115 void PitchBend(uint16_t pitch_bend) { 116 mod_pitch_bend_ = pitch_bend; 117 } Aftertouch(uint8_t velocity)118 void Aftertouch(uint8_t velocity) { 119 mod_aux_[2] = velocity << 9; 120 } 121 set_modulation_rate(uint8_t modulation_rate)122 inline void set_modulation_rate(uint8_t modulation_rate) { 123 modulation_rate_ = modulation_rate; 124 } set_pitch_bend_range(uint8_t pitch_bend_range)125 inline void set_pitch_bend_range(uint8_t pitch_bend_range) { 126 pitch_bend_range_ = pitch_bend_range; 127 } set_vibrato_range(uint8_t vibrato_range)128 inline void set_vibrato_range(uint8_t vibrato_range) { 129 vibrato_range_ = vibrato_range; 130 } set_trigger_duration(uint8_t trigger_duration)131 inline void set_trigger_duration(uint8_t trigger_duration) { 132 trigger_duration_ = trigger_duration; 133 } set_trigger_scale(uint8_t trigger_scale)134 inline void set_trigger_scale(uint8_t trigger_scale) { 135 trigger_scale_ = trigger_scale; 136 } set_trigger_shape(uint8_t trigger_shape)137 inline void set_trigger_shape(uint8_t trigger_shape) { 138 trigger_shape_ = trigger_shape; 139 } set_aux_cv(uint8_t aux_cv_source)140 inline void set_aux_cv(uint8_t aux_cv_source) { 141 aux_cv_source_ = aux_cv_source; 142 } set_aux_cv_2(uint8_t aux_cv_source_2)143 inline void set_aux_cv_2(uint8_t aux_cv_source_2) { 144 aux_cv_source_2_ = aux_cv_source_2; 145 } 146 note()147 inline int32_t note() const { return note_; } velocity()148 inline uint8_t velocity() const { return mod_velocity_; } modulation()149 inline uint8_t modulation() const { return mod_wheel_; } aux_cv()150 inline uint8_t aux_cv() const { return mod_aux_[aux_cv_source_] >> 8; } aux_cv_2()151 inline uint8_t aux_cv_2() const { return mod_aux_[aux_cv_source_2_] >> 8; } 152 DacCodeFrom16BitValue(uint16_t value)153 inline uint16_t DacCodeFrom16BitValue(uint16_t value) const { 154 uint32_t v = static_cast<uint32_t>(value); 155 uint32_t scale = calibrated_dac_code_[3] - calibrated_dac_code_[8]; 156 return static_cast<uint16_t>(calibrated_dac_code_[3] - (scale * v >> 16)); 157 } 158 note_dac_code()159 inline uint16_t note_dac_code() const { 160 return note_dac_code_; 161 } 162 velocity_dac_code()163 inline uint16_t velocity_dac_code() const { 164 return DacCodeFrom16BitValue(mod_velocity_ << 9); 165 } modulation_dac_code()166 inline uint16_t modulation_dac_code() const { 167 return DacCodeFrom16BitValue(mod_wheel_ << 9); 168 } aux_cv_dac_code()169 inline uint16_t aux_cv_dac_code() const { 170 return DacCodeFrom16BitValue(mod_aux_[aux_cv_source_]); 171 } aux_cv_dac_code_2()172 inline uint16_t aux_cv_dac_code_2() const { 173 return DacCodeFrom16BitValue(mod_aux_[aux_cv_source_2_]); 174 } 175 gate_on()176 inline bool gate_on() const { return gate_; } 177 gate()178 inline bool gate() const { return gate_ && !retrigger_delay_; } trigger()179 inline bool trigger() const { 180 return gate_ && trigger_pulse_; 181 } 182 183 uint16_t trigger_dac_code() const; 184 calibration_dac_code(uint8_t note)185 inline uint16_t calibration_dac_code(uint8_t note) const { 186 return calibrated_dac_code_[note]; 187 } 188 set_calibration_dac_code(uint8_t note,uint16_t dac_code)189 inline void set_calibration_dac_code(uint8_t note, uint16_t dac_code) { 190 calibrated_dac_code_[note] = dac_code; 191 dirty_ = true; 192 } 193 set_audio_mode(uint8_t audio_mode)194 inline void set_audio_mode(uint8_t audio_mode) { 195 audio_mode_ = audio_mode; 196 } 197 set_tuning(int8_t coarse,int8_t fine)198 inline void set_tuning(int8_t coarse, int8_t fine) { 199 tuning_ = (static_cast<int32_t>(coarse) << 7) + fine; 200 } 201 audio_mode()202 inline uint8_t audio_mode() { 203 return audio_mode_; 204 } RenderAudio()205 inline void RenderAudio() { 206 oscillator_.Render(audio_mode_, note_, gate_); 207 } ReadSample()208 inline uint16_t ReadSample() { 209 return oscillator_.ReadSample(); 210 } 211 TapLfo(uint32_t target_phase)212 void TapLfo(uint32_t target_phase) { 213 uint32_t target_increment = target_phase - lfo_pll_previous_target_phase_; 214 215 int32_t d_error = target_increment - (lfo_phase_ - lfo_pll_previous_phase_); 216 int32_t p_error = target_phase - lfo_phase_; 217 int32_t error = d_error + (p_error >> 1); 218 219 lfo_pll_phase_increment_ += error >> 11; 220 221 lfo_pll_previous_phase_ = lfo_phase_; 222 lfo_pll_previous_target_phase_ = target_phase; 223 } 224 225 private: 226 uint16_t NoteToDacCode(int32_t note) const; 227 void FillAudioBuffer(); 228 229 int32_t note_source_; 230 int32_t note_target_; 231 int32_t note_portamento_; 232 int32_t note_; 233 int32_t tuning_; 234 bool gate_; 235 236 bool dirty_; // Set to true when the calibration settings have changed. 237 uint16_t note_dac_code_; 238 uint16_t calibrated_dac_code_[kNumOctaves]; 239 240 int16_t mod_pitch_bend_; 241 uint8_t mod_wheel_; 242 uint16_t mod_aux_[8]; 243 uint8_t mod_velocity_; 244 245 uint8_t pitch_bend_range_; 246 uint8_t modulation_rate_; 247 uint8_t vibrato_range_; 248 249 uint8_t trigger_duration_; 250 uint8_t trigger_shape_; 251 bool trigger_scale_; 252 uint8_t aux_cv_source_; 253 uint8_t aux_cv_source_2_; 254 255 uint32_t lfo_phase_; 256 uint32_t portamento_phase_; 257 uint32_t portamento_phase_increment_; 258 bool portamento_exponential_shape_; 259 260 // This counter is used to artificially create a 500µs dip at LOW level when 261 // the gate is currently HIGH and a new note arrive with a retrigger command. 262 // This happens with note-stealing; or when sending a MIDI sequence with 263 // overlapping notes. 264 uint16_t retrigger_delay_; 265 266 uint16_t trigger_pulse_; 267 uint32_t trigger_phase_increment_; 268 uint32_t trigger_phase_; 269 270 // PLL for clock-synced LFO. 271 uint32_t lfo_pll_phase_increment_; 272 uint32_t lfo_pll_previous_target_phase_; 273 uint32_t lfo_pll_previous_phase_; 274 275 uint8_t audio_mode_; 276 Oscillator oscillator_; 277 278 DISALLOW_COPY_AND_ASSIGN(Voice); 279 }; 280 281 } // namespace yarns 282 283 #endif // YARNS_VOICE_H_ 284