Files

copied
Last update 6 years 2 months by Olivier Gillet
Filesplaitsdspengine
..
additive_engine.cc
additive_engine.h
bass_drum_engine.cc
bass_drum_engine.h
chord_engine.cc
chord_engine.h
engine.h
fm_engine.cc
fm_engine.h
grain_engine.cc
grain_engine.h
hi_hat_engine.cc
hi_hat_engine.h
modal_engine.cc
modal_engine.h
noise_engine.cc
noise_engine.h
particle_engine.cc
particle_engine.h
snare_drum_engine.cc
snare_drum_engine.h
speech_engine.cc
speech_engine.h
string_engine.cc
string_engine.h
swarm_engine.cc
swarm_engine.h
virtual_analog_engine.cc
virtual_analog_engine.h
waveshaping_engine.cc
waveshaping_engine.h
wavetable_engine.cc
wavetable_engine.h
swarm_engine.h
// Copyright 2016 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. // // ----------------------------------------------------------------------------- // // Swarm of sawtooths and sines. #ifndef PLAITS_DSP_ENGINE_SWARM_ENGINE_H_ #define PLAITS_DSP_ENGINE_SWARM_ENGINE_H_ #include "stmlib/dsp/polyblep.h" #include "stmlib/dsp/units.h" #include "stmlib/utils/random.h" #include "plaits/dsp/engine/engine.h" #include "plaits/dsp/oscillator/oscillator.h" #include "plaits/dsp/oscillator/string_synth_oscillator.h" #include "plaits/dsp/oscillator/sine_oscillator.h" #include "plaits/resources.h" namespace plaits { const int kNumSwarmVoices = 8; class GrainEnvelope { public: GrainEnvelope() { } ~GrainEnvelope() { } void Init() { from_ = 0.0f; interval_ = 1.0f; phase_ = 1.0f; fm_ = 0.0f; amplitude_ = 0.5f; previous_size_ratio_ = 0.0f; } inline void Step(float rate, bool burst_mode, bool start_burst) { bool randomize = false; if (start_burst) { phase_ = 0.5f; fm_ = 16.0f; randomize = true; } else { phase_ += rate * fm_; if (phase_ >= 1.0f) { phase_ -= static_cast<float>(static_cast<int>(phase_)); randomize = true; } } if (randomize) { from_ += interval_; interval_ = stmlib::Random::GetFloat() - from_; // Randomize the duration of the grain. if (burst_mode) { fm_ *= 0.8f + 0.2f * stmlib::Random::GetFloat(); } else { fm_ = 0.5f + 1.5f * stmlib::Random::GetFloat(); } } } inline float frequency(float size_ratio) const { // We approximate two overlapping grains of frequencies f1 and f2 // By a continuous tone ramping from f1 to f2. This allows a continuous // transition between the "grain cloud" and "swarm of glissandi" textures. if (size_ratio < 1.0f) { return 2.0f * (from_ + interval_ * phase_) - 1.0f; } else { return from_; } } inline float amplitude(float size_ratio) { float target_amplitude = 1.0f; if (size_ratio >= 1.0f) { float phase = (phase_ - 0.5f) * size_ratio; CONSTRAIN(phase, -1.0f, 1.0f); float e = stmlib::InterpolateWrap( lut_sine, 0.5f * phase + 1.25f, 1024.0f); target_amplitude = 0.5f * (e + 1.0f); } if ((size_ratio >= 1.0f) ^ (previous_size_ratio_ >= 1.0f)) { filter_coefficient_ = 0.5f; } filter_coefficient_ *= 0.95f; previous_size_ratio_ = size_ratio; ONE_POLE(amplitude_, target_amplitude, 0.5f - filter_coefficient_); return amplitude_; } private: float from_; float interval_; float phase_; float fm_; float amplitude_; float previous_size_ratio_; float filter_coefficient_; DISALLOW_COPY_AND_ASSIGN(GrainEnvelope); }; class AdditiveSawOscillator { public: AdditiveSawOscillator() { } ~AdditiveSawOscillator() { } inline void Init() { phase_ = 0.0f; next_sample_ = 0.0f; frequency_ = 0.01f; gain_ = 0.0f; } inline void Render( float frequency, float level, float* out, size_t size) { if (frequency >= kMaxFrequency) { frequency = kMaxFrequency; } stmlib::ParameterInterpolator fm(&frequency_, frequency, size); stmlib::ParameterInterpolator gain(&gain_, level, size); float next_sample = next_sample_; float phase = phase_; while (size--) { float this_sample = next_sample; next_sample = 0.0f; const float frequency = fm.Next(); phase += frequency; if (phase >= 1.0f) { phase -= 1.0f; float t = phase / frequency; this_sample -= stmlib::ThisBlepSample(t); next_sample -= stmlib::NextBlepSample(t); } next_sample += phase; *out++ += (2.0f * this_sample - 1.0f) * gain.Next(); } phase_ = phase; next_sample_ = next_sample; } private: // Oscillator state. float phase_; float next_sample_; // For interpolation of parameters. float frequency_; float gain_; DISALLOW_COPY_AND_ASSIGN(AdditiveSawOscillator); }; class SwarmVoice { public: SwarmVoice() { } ~SwarmVoice() { } void Init(float rank) { rank_ = rank; envelope_.Init(); saw_.Init(); sine_.Init(); } void Render( float f0, float density, bool burst_mode, bool start_burst, float spread, float size_ratio, float* saw, float* sine, size_t size) { envelope_.Step(density, burst_mode, start_burst); const float scale = 1.0f / kNumSwarmVoices; const float amplitude = envelope_.amplitude(size_ratio) * scale; const float expo_amount = envelope_.frequency(size_ratio); f0 *= stmlib::SemitonesToRatio(48.0f * expo_amount * spread * rank_); const float linear_amount = rank_ * (rank_ + 0.01f) * spread * 0.25f; f0 *= 1.0f + linear_amount; saw_.Render(f0, amplitude, saw, size); sine_.Render(f0, amplitude, sine, size); }; private: float rank_; GrainEnvelope envelope_; AdditiveSawOscillator saw_; FastSineOscillator sine_; }; class SwarmEngine : public Engine { public: SwarmEngine() { } ~SwarmEngine() { } virtual void Init(stmlib::BufferAllocator* allocator); virtual void Reset(); virtual void Render(const EngineParameters& parameters, float* out, float* aux, size_t size, bool* already_enveloped); private: SwarmVoice swarm_voice_[kNumSwarmVoices]; DISALLOW_COPY_AND_ASSIGN(SwarmEngine); }; } // namespace plaits #endif // PLAITS_DSP_ENGINE_SWARM_ENGINE_H_
Report a bug