Files

copied
Last update 5 years 8 months
Filesbraids
..
bootloader
data
drivers
hardware_design
resources
test
README.md
__init__.py
analog_oscillator.cc
analog_oscillator.h
braids.cc
digital_oscillator.cc
digital_oscillator.h
envelope.h
excitation.h
macro_oscillator.cc
macro_oscillator.h
makefile
parameter_interpolation.h
quantizer.cc
quantizer.h
quantizer_scales.h
resources.cc
resources.h
settings.cc
settings.h
signature_waveshaper.h
svf.h
ui.cc
ui.h
vco_jitter_source.h
analog_oscillator.cc
// Copyright 2012 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. // // ----------------------------------------------------------------------------- // // Oscillator - analog style waveforms. #include "braids/analog_oscillator.h" #include "stmlib/utils/dsp.h" #include "braids/resources.h" #include "braids/parameter_interpolation.h" namespace braids { using namespace stmlib; static const size_t kNumZones = 15; static const uint16_t kHighestNote = 128 * 128; static const uint16_t kPitchTableStart = 128 * 128; static const uint16_t kOctave = 12 * 128; uint32_t AnalogOscillator::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 AnalogOscillator::Render( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { RenderFn fn = fn_table_[shape_]; if (shape_ != previous_shape_) { Init(); previous_shape_ = shape_; } phase_increment_ = ComputePhaseIncrement(pitch_); if (pitch_ > kHighestNote) { pitch_ = kHighestNote; } else if (pitch_ < 0) { pitch_ = 0; } (this->*fn)(sync_in, buffer, sync_out, size); } void AnalogOscillator::RenderCSaw( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { BEGIN_INTERPOLATE_PHASE_INCREMENT int32_t next_sample = next_sample_; while (size--) { bool sync_reset = false; bool self_reset = false; bool transition_during_reset = false; uint32_t reset_time = 0; INTERPOLATE_PHASE_INCREMENT uint32_t pw = static_cast<uint32_t>(parameter_) * 49152; if (pw < 8 * phase_increment) { pw = 8 * phase_increment; } int32_t this_sample = next_sample; next_sample = 0; if (*sync_in) { // sync_in contain the fractional reset time. reset_time = static_cast<uint32_t>(*sync_in - 1) << 9; uint32_t phase_at_reset = phase_ + \ (65535 - reset_time) * (phase_increment >> 16); sync_reset = true; transition_during_reset = false; if (phase_at_reset < phase_ || (!high_ && phase_at_reset >= pw)) { transition_during_reset = true; } if (phase_ >= pw) { discontinuity_depth_ = -2048 + (aux_parameter_ >> 2); int32_t before = (phase_at_reset >> 18); int16_t after = discontinuity_depth_; int32_t discontinuity = after - before; this_sample += discontinuity * ThisBlepSample(reset_time) >> 15; next_sample += discontinuity * NextBlepSample(reset_time) >> 15; } } sync_in++; phase_ += phase_increment; if (phase_ < phase_increment) { self_reset = true; } if (sync_out) { if (phase_ < phase_increment) { *sync_out++ = phase_ / (phase_increment >> 7) + 1; } else { *sync_out++ = 0; } } while (transition_during_reset || !sync_reset) { if (!high_) { if (phase_ < pw) { break; } uint32_t t = (phase_ - pw) / (phase_increment >> 16); int16_t before = discontinuity_depth_; int16_t after = phase_ >> 18; int16_t discontinuity = after - before; this_sample += discontinuity * ThisBlepSample(t) >> 15; next_sample += discontinuity * NextBlepSample(t) >> 15; high_ = true; } if (high_) { if (!self_reset) { break; } self_reset = false; discontinuity_depth_ = -2048 + (aux_parameter_ >> 2); uint32_t t = phase_ / (phase_increment >> 16); int16_t before = 16383; int16_t after = discontinuity_depth_; int16_t discontinuity = after - before; this_sample += discontinuity * ThisBlepSample(t) >> 15; next_sample += discontinuity * NextBlepSample(t) >> 15; high_ = false; } } if (sync_reset) { phase_ = reset_time * (phase_increment >> 16); high_ = false; } next_sample += phase_ < pw ? discontinuity_depth_ : phase_ >> 18; *buffer++ = (this_sample - 8192) << 1; } next_sample_ = next_sample; END_INTERPOLATE_PHASE_INCREMENT } void AnalogOscillator::RenderSquare( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { BEGIN_INTERPOLATE_PHASE_INCREMENT if (parameter_ > 32000) { parameter_ = 32000; } int32_t next_sample = next_sample_; while (size--) { bool sync_reset = false; bool self_reset = false; bool transition_during_reset = false; uint32_t reset_time = 0; INTERPOLATE_PHASE_INCREMENT uint32_t pw = static_cast<uint32_t>(32768 - parameter_) << 16; int32_t this_sample = next_sample; next_sample = 0; if (*sync_in) { // sync_in contain the fractional reset time. reset_time = static_cast<uint32_t>(*sync_in - 1) << 9; uint32_t phase_at_reset = phase_ + \ (65535 - reset_time) * (phase_increment >> 16); sync_reset = true; if (phase_at_reset < phase_ || (!high_ && phase_at_reset >= pw)) { transition_during_reset = true; } if (phase_at_reset >= pw) { this_sample -= ThisBlepSample(reset_time); next_sample -= NextBlepSample(reset_time); } } sync_in++; phase_ += phase_increment; if (phase_ < phase_increment) { self_reset = true; } if (sync_out) { if (phase_ < phase_increment) { *sync_out++ = phase_ / (phase_increment >> 7) + 1; } else { *sync_out++ = 0; } } while (transition_during_reset || !sync_reset) { if (!high_) { if (phase_ < pw) { break; } uint32_t t = (phase_ - pw) / (phase_increment >> 16); this_sample += ThisBlepSample(t); next_sample += NextBlepSample(t); high_ = true; } if (high_) { if (!self_reset) { break; } self_reset = false; uint32_t t = phase_ / (phase_increment >> 16); this_sample -= ThisBlepSample(t); next_sample -= NextBlepSample(t); high_ = false; } } if (sync_reset) { phase_ = reset_time * (phase_increment >> 16); high_ = false; } next_sample += phase_ < pw ? 0 : 32767; *buffer++ = (this_sample - 16384) << 1; } next_sample_ = next_sample; END_INTERPOLATE_PHASE_INCREMENT } void AnalogOscillator::RenderSaw( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { BEGIN_INTERPOLATE_PHASE_INCREMENT int32_t next_sample = next_sample_; while (size--) { bool sync_reset = false; bool self_reset = false; bool transition_during_reset = false; uint32_t reset_time = 0; INTERPOLATE_PHASE_INCREMENT int32_t this_sample = next_sample; next_sample = 0; if (*sync_in) { // sync_in contain the fractional reset time. reset_time = static_cast<uint32_t>(*sync_in - 1) << 9; uint32_t phase_at_reset = phase_ + \ (65535 - reset_time) * (phase_increment >> 16); sync_reset = true; if (phase_at_reset < phase_) { transition_during_reset = true; } int32_t discontinuity = phase_at_reset >> 17; this_sample -= discontinuity * ThisBlepSample(reset_time) >> 15; next_sample -= discontinuity * NextBlepSample(reset_time) >> 15; } sync_in++; phase_ += phase_increment; if (phase_ < phase_increment) { self_reset = true; } if (sync_out) { if (phase_ < phase_increment) { *sync_out++ = phase_ / (phase_increment >> 7) + 1; } else { *sync_out++ = 0; } } if ((transition_during_reset || !sync_reset) && self_reset) { uint32_t t = phase_ / (phase_increment >> 16); this_sample -= ThisBlepSample(t); next_sample -= NextBlepSample(t); } if (sync_reset) { phase_ = reset_time * (phase_increment >> 16); high_ = false; } next_sample += phase_ >> 17; *buffer++ = (this_sample - 16384) << 1; } next_sample_ = next_sample; END_INTERPOLATE_PHASE_INCREMENT } void AnalogOscillator::RenderVariableSaw( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { BEGIN_INTERPOLATE_PHASE_INCREMENT int32_t next_sample = next_sample_; if (parameter_ < 1024) { parameter_ = 1024; } while (size--) { bool sync_reset = false; bool self_reset = false; bool transition_during_reset = false; uint32_t reset_time = 0; INTERPOLATE_PHASE_INCREMENT uint32_t pw = static_cast<uint32_t>(parameter_) << 16; int32_t this_sample = next_sample; next_sample = 0; if (*sync_in) { // sync_in contain the fractional reset time. reset_time = static_cast<uint32_t>(*sync_in - 1) << 9; uint32_t phase_at_reset = phase_ + \ (65535 - reset_time) * (phase_increment >> 16); sync_reset = true; if (phase_at_reset < phase_ || (!high_ && phase_at_reset >= pw)) { transition_during_reset = true; } int32_t before = (phase_at_reset >> 18) + ((phase_at_reset - pw) >> 18); int32_t after = (0 >> 18) + ((0 - pw) >> 18); int32_t discontinuity = after - before; this_sample += discontinuity * ThisBlepSample(reset_time) >> 15; next_sample += discontinuity * NextBlepSample(reset_time) >> 15; } sync_in++; phase_ += phase_increment; if (phase_ < phase_increment) { self_reset = true; } if (sync_out) { if (phase_ < phase_increment) { *sync_out++ = phase_ / (phase_increment >> 7) + 1; } else { *sync_out++ = 0; } } while (transition_during_reset || !sync_reset) { if (!high_) { if (phase_ < pw) { break; } uint32_t t = (phase_ - pw) / (phase_increment >> 16); this_sample -= ThisBlepSample(t) >> 1; next_sample -= NextBlepSample(t) >> 1; high_ = true; } if (high_) { if (!self_reset) { break; } self_reset = false; uint32_t t = phase_ / (phase_increment >> 16); this_sample -= ThisBlepSample(t) >> 1; next_sample -= NextBlepSample(t) >> 1; high_ = false; } } if (sync_reset) { phase_ = reset_time * (phase_increment >> 16); high_ = false; } next_sample += phase_ >> 18; next_sample += (phase_ - pw) >> 18; *buffer++ = (this_sample - 16384) << 1; } next_sample_ = next_sample; END_INTERPOLATE_PHASE_INCREMENT } void AnalogOscillator::RenderTriangle( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { BEGIN_INTERPOLATE_PHASE_INCREMENT uint32_t phase = phase_; while (size--) { INTERPOLATE_PHASE_INCREMENT int16_t triangle; uint16_t phase_16; if (*sync_in++) { phase = 0; } phase += phase_increment >> 1; phase_16 = phase >> 16; triangle = (phase_16 << 1) ^ (phase_16 & 0x8000 ? 0xffff : 0x0000); triangle += 32768; *buffer = triangle >> 1; phase += phase_increment >> 1; phase_16 = phase >> 16; triangle = (phase_16 << 1) ^ (phase_16 & 0x8000 ? 0xffff : 0x0000); triangle += 32768; *buffer++ += triangle >> 1; } phase_ = phase; END_INTERPOLATE_PHASE_INCREMENT } void AnalogOscillator::RenderSine( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { uint32_t phase = phase_; BEGIN_INTERPOLATE_PHASE_INCREMENT while (size--) { INTERPOLATE_PHASE_INCREMENT phase += phase_increment; if (*sync_in++) { phase = 0; } *buffer++ = Interpolate824(wav_sine, phase); } END_INTERPOLATE_PHASE_INCREMENT phase_ = phase; } void AnalogOscillator::RenderTriangleFold( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { uint32_t phase = phase_; BEGIN_INTERPOLATE_PHASE_INCREMENT BEGIN_INTERPOLATE_PARAMETER while (size--) { INTERPOLATE_PARAMETER INTERPOLATE_PHASE_INCREMENT uint16_t phase_16; int16_t triangle; int16_t gain = 2048 + (parameter * 30720 >> 15); if (*sync_in++) { phase = 0; } // 2x oversampled WF. phase += phase_increment >> 1; phase_16 = phase >> 16; triangle = (phase_16 << 1) ^ (phase_16 & 0x8000 ? 0xffff : 0x0000); triangle += 32768; triangle = triangle * gain >> 15; triangle = Interpolate88(ws_tri_fold, triangle + 32768); *buffer = triangle >> 1; phase += phase_increment >> 1; phase_16 = phase >> 16; triangle = (phase_16 << 1) ^ (phase_16 & 0x8000 ? 0xffff : 0x0000); triangle += 32768; triangle = triangle * gain >> 15; triangle = Interpolate88(ws_tri_fold, triangle + 32768); *buffer++ += triangle >> 1; } END_INTERPOLATE_PARAMETER END_INTERPOLATE_PHASE_INCREMENT phase_ = phase; } void AnalogOscillator::RenderSineFold( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { uint32_t phase = phase_; BEGIN_INTERPOLATE_PHASE_INCREMENT BEGIN_INTERPOLATE_PARAMETER while (size--) { INTERPOLATE_PARAMETER INTERPOLATE_PHASE_INCREMENT int16_t sine; int16_t gain = 2048 + (parameter * 30720 >> 15); if (*sync_in++) { phase = 0; } // 2x oversampled WF. phase += phase_increment >> 1; sine = Interpolate824(wav_sine, phase); sine = sine * gain >> 15; sine = Interpolate88(ws_sine_fold, sine + 32768); *buffer = sine >> 1; phase += phase_increment >> 1; sine = Interpolate824(wav_sine, phase); sine = sine * gain >> 15; sine = Interpolate88(ws_sine_fold, sine + 32768); *buffer++ += sine >> 1; } END_INTERPOLATE_PARAMETER END_INTERPOLATE_PHASE_INCREMENT phase_ = phase; } void AnalogOscillator::RenderBuzz( const uint8_t* sync_in, int16_t* buffer, uint8_t* sync_out, size_t size) { int32_t shifted_pitch = pitch_ + ((32767 - parameter_) >> 1); uint16_t crossfade = shifted_pitch << 6; size_t index = (shifted_pitch >> 10); if (index >= kNumZones) { index = kNumZones - 1; } const int16_t* wave_1 = waveform_table[WAV_BANDLIMITED_COMB_0 + index]; index += 1; if (index >= kNumZones) { index = kNumZones - 1; } const int16_t* wave_2 = waveform_table[WAV_BANDLIMITED_COMB_0 + index]; while (size--) { phase_ += phase_increment_; if (*sync_in++) { phase_ = 0; } *buffer++ = Crossfade(wave_1, wave_2, phase_, crossfade); } } /* static */ AnalogOscillator::RenderFn AnalogOscillator::fn_table_[] = { &AnalogOscillator::RenderSaw, &AnalogOscillator::RenderVariableSaw, &AnalogOscillator::RenderCSaw, &AnalogOscillator::RenderSquare, &AnalogOscillator::RenderTriangle, &AnalogOscillator::RenderSine, &AnalogOscillator::RenderTriangleFold, &AnalogOscillator::RenderSineFold, &AnalogOscillator::RenderBuzz, }; } // namespace braids
Report a bug