|
- // Copyright 2013 Olivier Gillet.
- //
- // Author: Olivier Gillet (ol.gillet@gmail.com)
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- // See http://creativecommons.org/licenses/MIT/ for more information.
- //
- // -----------------------------------------------------------------------------
- //
- // Voice.
-
- #include "yarns/voice.h"
-
- #include <algorithm>
- #include <cstdio>
- #include <cstdlib>
-
- #include "stmlib/midi/midi.h"
- #include "stmlib/utils/dsp.h"
- #include "stmlib/utils/random.h"
-
- #include "yarns/resources.h"
-
- namespace yarns {
-
- using namespace stmlib;
- using namespace stmlib_midi;
-
- const int32_t kOctave = 12 << 7;
- const int32_t kMaxNote = 120 << 7;
-
- void Voice::Init() {
- note_ = -1;
- note_source_ = note_target_ = note_portamento_ = 60 << 7;
- gate_ = false;
-
- mod_velocity_ = 0;
- ResetAllControllers();
-
- modulation_rate_ = 0;
- pitch_bend_range_ = 2;
- vibrato_range_ = 0;
-
- lfo_phase_ = portamento_phase_ = 0;
- portamento_phase_increment_ = 1U << 31;
- portamento_exponential_shape_ = false;
-
- trigger_duration_ = 2;
- for (uint8_t i = 0; i < kNumOctaves; ++i) {
- calibrated_dac_code_[i] = 54586 - 5133 * i;
- }
- dirty_ = false;
- oscillator_.Init(
- calibrated_dac_code_[3] - calibrated_dac_code_[8],
- calibrated_dac_code_[3]);
- }
-
- void Voice::Calibrate(uint16_t* calibrated_dac_code) {
- std::copy(
- &calibrated_dac_code[0],
- &calibrated_dac_code[kNumOctaves],
- &calibrated_dac_code_[0]);
- }
-
- inline uint16_t Voice::NoteToDacCode(int32_t note) const {
- if (note <= 0) {
- note = 0;
- }
- if (note >= kMaxNote) {
- note = kMaxNote - 1;
- }
- uint8_t octave = 0;
- while (note >= kOctave) {
- note -= kOctave;
- ++octave;
- }
-
- // Note is now between 0 and kOctave
- // Octave indicates the octave. Look up in the DAC code table.
- int32_t a = calibrated_dac_code_[octave];
- int32_t b = calibrated_dac_code_[octave + 1];
- return a + ((b - a) * note / kOctave);
- }
-
- void Voice::ResetAllControllers() {
- mod_pitch_bend_ = 8192;
- mod_wheel_ = 0;
- std::fill(&mod_aux_[0], &mod_aux_[7], 0);
- }
-
- void Voice::Refresh() {
- // Compute base pitch with portamento.
- portamento_phase_ += portamento_phase_increment_;
- if (portamento_phase_ < portamento_phase_increment_) {
- portamento_phase_ = 0;
- portamento_phase_increment_ = 0;
- note_source_ = note_target_;
- }
- uint16_t portamento_level = portamento_exponential_shape_
- ? Interpolate824(lut_env_expo, portamento_phase_)
- : portamento_phase_ >> 16;
- int32_t note = note_source_ + \
- ((note_target_ - note_source_) * portamento_level >> 16);
-
- note_portamento_ = note;
-
- // Add pitch-bend.
- note += static_cast<int32_t>(mod_pitch_bend_ - 8192) * pitch_bend_range_ >> 6;
-
- // Add transposition/fine tuning.
- note += tuning_;
-
- // Add vibrato.
- if (modulation_rate_ < 100) {
- lfo_phase_ += lut_lfo_increments[modulation_rate_];
- } else {
- lfo_phase_ += lfo_pll_phase_increment_;
- }
- int32_t lfo = lfo_phase_ < 1UL << 31
- ? -32768 + (lfo_phase_ >> 15)
- : 0x17fff - (lfo_phase_ >> 15);
- note += lfo * mod_wheel_ * vibrato_range_ >> 15;
- mod_aux_[0] = mod_velocity_ << 9;
- mod_aux_[1] = mod_wheel_ << 9;
- mod_aux_[5] = static_cast<uint16_t>(mod_pitch_bend_) << 2;
- mod_aux_[6] = (lfo * mod_wheel_ >> 7) + 32768;
- mod_aux_[7] = lfo + 32768;
-
- if (retrigger_delay_) {
- --retrigger_delay_;
- }
-
- if (trigger_pulse_) {
- --trigger_pulse_;
- }
-
- if (trigger_phase_increment_) {
- trigger_phase_ += trigger_phase_increment_;
- if (trigger_phase_ < trigger_phase_increment_) {
- trigger_phase_ = 0;
- trigger_phase_increment_ = 0;
- }
- }
- if (note != note_ || dirty_) {
- note_dac_code_ = NoteToDacCode(note);
- note_ = note;
- dirty_ = false;
- }
- }
-
- void Voice::NoteOn(
- int16_t note,
- uint8_t velocity,
- uint8_t portamento,
- bool trigger) {
- note_source_ = note_portamento_;
- note_target_ = note;
- if (!portamento) {
- note_source_ = note_target_;
- }
- portamento_phase_ = 0;
- if (portamento <= 50) {
- portamento_phase_increment_ = lut_portamento_increments[portamento << 1];
- portamento_exponential_shape_ = true;
- } else {
- uint32_t base_increment = lut_portamento_increments[(portamento - 51) << 1];
- uint32_t delta = abs(note_target_ - note_source_) + 1;
- portamento_phase_increment_ = (1536 * (base_increment >> 11) / delta) << 11;
- CONSTRAIN(portamento_phase_increment_, 1, 2147483647);
- portamento_exponential_shape_ = false;
- }
-
- mod_velocity_ = velocity;
-
- if (gate_ && trigger) {
- retrigger_delay_ = 2;
- }
- if (trigger) {
- trigger_pulse_ = trigger_duration_ * 8;
- trigger_phase_ = 0;
- trigger_phase_increment_ = lut_portamento_increments[trigger_duration_];
- }
- gate_ = true;
- }
-
- void Voice::NoteOff() {
- gate_ = false;
- }
-
- void Voice::ControlChange(uint8_t controller, uint8_t value) {
- switch (controller) {
- case kCCModulationWheelMsb:
- mod_wheel_ = value;
- break;
-
- case kCCBreathController:
- mod_aux_[3] = value << 9;
- break;
-
- case kCCFootPedalMsb:
- mod_aux_[4] = value << 9;
- break;
- }
- }
-
- uint16_t Voice::trigger_dac_code() const {
- if (trigger_phase_ <= trigger_phase_increment_) {
- return calibrated_dac_code_[3]; // 0V.
- } else {
- int32_t velocity_coefficient = trigger_scale_ ? mod_velocity_ << 8 : 32768;
- int32_t value = 0;
- switch(trigger_shape_) {
- case TRIGGER_SHAPE_SQUARE:
- value = 32767;
- break;
- case TRIGGER_SHAPE_LINEAR:
- value = 32767 - (trigger_phase_ >> 17);
- break;
- default:
- {
- const int16_t* table = waveform_table[
- trigger_shape_ - TRIGGER_SHAPE_EXPONENTIAL];
- value = Interpolate824(table, trigger_phase_);
- }
- break;
- }
- value = value * velocity_coefficient >> 15;
- int32_t max = calibrated_dac_code_[8];
- int32_t min = calibrated_dac_code_[3];
- return min + ((max - min) * value >> 15);
- }
- }
-
- static const uint16_t kHighestNote = 128 * 128;
- static const uint16_t kPitchTableStart = 116 * 128;
-
-
- void Oscillator::Init(int32_t scale, int32_t offset) {
- audio_buffer_.Init();
- phase_ = 0;
- next_sample_ = 0;
- high_ = false;
- scale_ = scale;
- offset_ = offset;
- integrator_state_ = 0;
- }
-
- uint32_t Oscillator::ComputePhaseIncrement(int16_t midi_pitch) {
- if (midi_pitch >= kHighestNote) {
- midi_pitch = kHighestNote - 1;
- }
-
- int32_t ref_pitch = midi_pitch;
- ref_pitch -= kPitchTableStart;
-
- size_t num_shifts = 0;
- while (ref_pitch < 0) {
- ref_pitch += kOctave;
- ++num_shifts;
- }
-
- uint32_t a = lut_oscillator_increments[ref_pitch >> 4];
- uint32_t b = lut_oscillator_increments[(ref_pitch >> 4) + 1];
- uint32_t phase_increment = a + \
- (static_cast<int32_t>(b - a) * (ref_pitch & 0xf) >> 4);
- phase_increment >>= num_shifts;
- return phase_increment;
- }
-
- void Oscillator::RenderSilence() {
- size_t size = kAudioBlockSize;
- while (size--) {
- audio_buffer_.Overwrite(offset_);
- }
- }
-
- void Oscillator::RenderSine(uint32_t phase_increment) {
- size_t size = kAudioBlockSize;
- while (size--) {
- phase_ += phase_increment;
- int32_t sample = Interpolate1022(wav_sine, phase_);
- audio_buffer_.Overwrite(offset_ - (scale_ * sample >> 16));
- }
- }
-
- void Oscillator::RenderNoise() {
- size_t size = kAudioBlockSize;
- while (size--) {
- int16_t sample = Random::GetSample();
- audio_buffer_.Overwrite(offset_ - (scale_ * sample >> 16));
- }
- }
-
- void Oscillator::RenderSaw(uint32_t phase_increment) {
- uint32_t phase = phase_;
- int32_t next_sample = next_sample_;
- size_t size = kAudioBlockSize;
-
- while (size--) {
- int32_t this_sample = next_sample;
- next_sample = 0;
- phase += phase_increment;
- if (phase < phase_increment) {
- uint32_t t = phase / (phase_increment >> 16);
- this_sample -= ThisBlepSample(t);
- next_sample -= NextBlepSample(t);
- }
- next_sample += phase >> 17;
- this_sample = (this_sample - 16384) << 1;
- audio_buffer_.Overwrite(offset_ - (scale_ * this_sample >> 16));
- }
- next_sample_ = next_sample;
- phase_ = phase;
- }
-
- void Oscillator::RenderSquare(
- uint32_t phase_increment,
- uint32_t pw,
- bool integrate) {
- uint32_t phase = phase_;
- int32_t next_sample = next_sample_;
- int32_t integrator_state = integrator_state_;
- int16_t integrator_coefficient = phase_increment >> 18;
- size_t size = kAudioBlockSize;
-
- while (size--) {
- int32_t this_sample = next_sample;
- next_sample = 0;
- phase += phase_increment;
-
- if (!high_) {
- if (phase >= pw) {
- uint32_t t = (phase - pw) / (phase_increment >> 16);
- this_sample += ThisBlepSample(t);
- next_sample += NextBlepSample(t);
- high_ = true;
- }
- }
- if (high_ && (phase < phase_increment)) {
- uint32_t t = phase / (phase_increment >> 16);
- this_sample -= ThisBlepSample(t);
- next_sample -= NextBlepSample(t);
- high_ = false;
- }
- next_sample += phase < pw ? 0 : 32767;
- this_sample = (this_sample - 16384) << 1;
- if (integrate) {
- integrator_state += integrator_coefficient * (this_sample - integrator_state) >> 15;
- this_sample = integrator_state << 3;
- }
- audio_buffer_.Overwrite(offset_ - (scale_ * this_sample >> 16));
- }
- integrator_state_ = integrator_state;
- next_sample_ = next_sample;
- phase_ = phase;
- }
-
- void Oscillator::Render(uint8_t mode, int16_t note, bool gate) {
- if (mode == 0 || audio_buffer_.writable() < kAudioBlockSize) {
- return;
- }
-
- if ((mode & 0x80) && !gate) {
- RenderSilence();
- return;
- }
-
- uint32_t phase_increment = ComputePhaseIncrement(note);
- switch ((mode & 0x0f) - 1) {
- case 0:
- RenderSaw(phase_increment);
- break;
- case 1:
- RenderSquare(phase_increment, 0x40000000, false);
- break;
- case 2:
- RenderSquare(phase_increment, 0x80000000, false);
- break;
- case 3:
- RenderSquare(phase_increment, 0x80000000, true);
- break;
- case 4:
- RenderSine(phase_increment);
- break;
- default:
- RenderNoise();
- break;
- }
- }
-
- } // namespace yarns
|