Files

copied
Last update 6 years 1 month by Olivier Gillet
Fileselementsdsp
..
fx
dsp.h
exciter.cc
exciter.h
multistage_envelope.cc
multistage_envelope.h
ominous_voice.cc
ominous_voice.h
part.cc
part.h
patch.h
resonator.cc
resonator.h
string.cc
string.h
tube.cc
tube.h
voice.cc
voice.h
exciter.cc
// Copyright 2014 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. // // ----------------------------------------------------------------------------- // // Exciter. #include "elements/dsp/exciter.h" #include <algorithm> #include "stmlib/dsp/dsp.h" #include "stmlib/dsp/units.h" #include "elements/dsp/dsp.h" #include "elements/resources.h" namespace elements { using namespace std; using namespace stmlib; void Exciter::Init() { set_model(EXCITER_MODEL_MALLET); set_parameter(0.0f); set_timbre(0.99f); lp_.Init(); damp_state_ = 0.0f; delay_ = 0; plectrum_delay_ = 0; particle_state_ = 0.5f; damping_ = 0.0f; signature_ = 0.0f; } float Exciter::GetPulseAmplitude(float cutoff) { uint32_t cutoff_index = static_cast<uint32_t>(cutoff * 256.0f); return lut_approx_svf_gain[cutoff_index]; } void Exciter::Process(const uint8_t flags, float* out, size_t size) { damping_ = 0.0f; (this->*fn_table_[model_])(flags, out, size); // Apply filters. if (model_ != EXCITER_MODEL_GRANULAR_SAMPLE_PLAYER && model_ != EXCITER_MODEL_SAMPLE_PLAYER) { uint32_t cutoff_index = static_cast<uint32_t>(timbre_ * 256.0f); if (model_ == EXCITER_MODEL_NOISE) { uint32_t resonance_index = static_cast<uint32_t>(parameter_ * 256.0f); lp_.set_g_r( lut_approx_svf_g[cutoff_index], lut_approx_svf_r[resonance_index]); } else { lp_.set_g_r_h( lut_approx_svf_g[cutoff_index], 2.0f, lut_approx_svf_h[cutoff_index]); } lp_.Process<FILTER_MODE_LOW_PASS>(out, out, size); } } void Exciter::ProcessGranularSamplePlayer( const uint8_t flags, float* out, size_t size) { const uint32_t restart_prob = uint32_t(0.01f * 4294967296.0f); const uint32_t restart_point = uint32_t(parameter_ * 32767.0f) << 17; const uint32_t phase_increment = static_cast<uint32_t>( 131072.0f * SemitonesToRatio(72.0f * timbre_ - 60.0f)); const int16_t* base = &smp_noise_sample[static_cast<size_t>( signature_ * 8192.0f)]; uint32_t phase = phase_; while (size--) { uint32_t phase_integral = phase >> 17; float phase_fractional = static_cast<float>(phase & 0x1ffff) / 131072.0f; float a = static_cast<float>(base[phase_integral]); float b = static_cast<float>(base[phase_integral + 1]); *out++ = (a + (b - a) * phase_fractional) / 32768.0f; phase += phase_increment; if (Random::GetWord() < restart_prob) { phase = restart_point; } } phase_ = phase; damping_ = 0.0f; } void Exciter::ProcessSamplePlayer( const uint8_t flags, float* out, size_t size) { float index = (1.0f - parameter_) * 8.0f; MAKE_INTEGRAL_FRACTIONAL(index); if (index_integral == 8) { index_integral = 7; index_fractional = 1.0f; } const uint32_t offset_1 = smp_boundaries[index_integral]; const uint32_t offset_2 = smp_boundaries[index_integral + 1]; const uint32_t length_1 = offset_2 - offset_1 - 1; const uint32_t length_2 = smp_boundaries[index_integral + 2] - offset_2 - 1; const uint32_t phase_increment = static_cast<uint32_t>( 65536.0f * SemitonesToRatio(72.0f * timbre_ - 36.0f + 7.0f)); float damp = damp_state_; uint32_t phase = phase_; if (flags & EXCITER_FLAG_RISING_EDGE) { damp = 0.0f; phase = 0; } if (!(flags & EXCITER_FLAG_GATE)) { damp = 1.0f - 0.95f * (1.0f - damp); } while (size--) { uint32_t phase_integral = phase >> 16; float phase_fractional = static_cast<float>(phase & 0xffff) / 65536.0f; float sample_1 = 0.0f; float sample_2 = 0.0f; bool step = false; if (phase_integral < length_1) { const int16_t* base = &smp_sample_data[offset_1 + phase_integral]; float a = static_cast<float>(base[0]); float b = static_cast<float>(base[1]); sample_1 = a + (b - a) * phase_fractional; step = true; } if (phase_integral < length_2) { const int16_t* base = &smp_sample_data[offset_2 + phase_integral]; float a = static_cast<float>(base[0]); float b = static_cast<float>(base[1]); sample_2 = a + (b - a) * phase_fractional; step = true; } if (step) { phase += phase_increment; } *out++ = (sample_1 + (sample_2 - sample_1) * index_fractional) / 65536.0f; } phase_ = phase; damping_ = damp * (parameter_ >= 0.8f ? parameter_ * 5.0f - 4.0f : 0.0f); damp_state_ = damp; } void Exciter::ProcessMallet(const uint8_t flags, float* out, size_t size) { fill(&out[0], &out[size], 0.0f); if (flags & EXCITER_FLAG_RISING_EDGE) { damp_state_ = 0.0f; out[0] = GetPulseAmplitude(timbre_); } if (!(flags & EXCITER_FLAG_GATE)) { damp_state_ = 1.0f - 0.95f * (1.0f - damp_state_); } damping_ = damp_state_ * (1.0f - parameter_); } void Exciter::ProcessPlectrum( const uint8_t flags, float* out, size_t size) { float amplitude = GetPulseAmplitude(timbre_); float damp = damp_state_; float impulse = 0.0f; if (flags & EXCITER_FLAG_RISING_EDGE) { impulse = -amplitude * (0.05f + signature_ * 0.2f); plectrum_delay_ = static_cast<uint32_t>( 4096.0f * parameter_ * parameter_) + 64; } while (size--) { if (plectrum_delay_) { --plectrum_delay_; if (plectrum_delay_ == 0) { impulse = amplitude; } damp = 1.0f - 0.997f * (1.0f - damp); } else { damp = 0.9f * damp; } *out++ = impulse; impulse = 0.0f; } damping_ = damp * 0.5f; damp_state_ = damp; } void Exciter::ProcessParticles( const uint8_t flags, float* out, size_t size) { if (flags & EXCITER_FLAG_RISING_EDGE) { particle_state_ = RandomSample(); particle_state_ = 1.0f - 0.6f * particle_state_ * particle_state_; delay_ = 0; particle_range_ = 1.0f; } fill(&out[0], &out[size], 0.0f); if (flags & EXCITER_FLAG_GATE) { const uint32_t up_probability = uint32_t(0.7f * 4294967296.0f); const uint32_t down_probability = uint32_t(0.3f * 4294967296.0f); const float amplitude = GetPulseAmplitude(timbre_); while (size--) { if (delay_ == 0) { float amount = RandomSample(); amount = 1.05f + 0.5f * amount * amount; if (Random::GetWord() > up_probability) { particle_state_ *= amount; if (particle_state_ >= (particle_range_ + 0.25f)) { particle_state_ = particle_range_ + 0.25f; } } else if (Random::GetWord() < down_probability) { particle_state_ /= amount; if (particle_state_ <= 0.02f) { particle_state_ = 0.02f; } } delay_ = static_cast<uint32_t>(particle_state_ * 0.15f * kSampleRate); float gain = 1.0f - particle_range_; gain *= gain; *out = particle_state_ * amplitude * (1.0f - gain); float decay_factor = 1.0f - parameter_; particle_range_ *= 1.0f - decay_factor * decay_factor * 0.5f; } else { --delay_; } ++out; } } } void Exciter::ProcessFlow( const uint8_t flags, float* out, size_t size) { float scale = parameter_ * parameter_ * parameter_ * parameter_; float threshold = 0.0001f + scale * 0.125f; if (flags & EXCITER_FLAG_RISING_EDGE) { particle_state_ = 0.5f; } while (size--) { float sample = RandomSample(); if (sample < threshold) { particle_state_ = -particle_state_; } *out++ = particle_state_ + (sample - 0.5f - particle_state_) * scale; } } void Exciter::ProcessNoise(const uint8_t flags, float* out, size_t size) { while (size--) { *out++ = RandomSample() - 0.5f; } } /* static */ Exciter::ProcessFn Exciter::fn_table_[] = { &Exciter::ProcessGranularSamplePlayer, &Exciter::ProcessSamplePlayer, &Exciter::ProcessMallet, &Exciter::ProcessPlectrum, &Exciter::ProcessParticles, &Exciter::ProcessFlow, &Exciter::ProcessNoise }; } // namespace elements
Report a bug