From 90978ea926ee36578f600c08f5ce182b389eeb60 Mon Sep 17 00:00:00 2001 From: stephenhensley Date: Fri, 1 Oct 2021 15:51:48 -0700 Subject: [PATCH 1/4] changed clamping of phasor to allow negative frequency --- Source/Control/phasor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Control/phasor.cpp b/Source/Control/phasor.cpp index 33ff9204..b505f6fa 100644 --- a/Source/Control/phasor.cpp +++ b/Source/Control/phasor.cpp @@ -21,7 +21,7 @@ float Phasor::Process() } if(phs_ < 0.0f) { - phs_ = 0.0f; + phs_ += TWOPI_F; } return out; } From 6bcc406508fdf22fd42ce041cbae88c337a20e4b Mon Sep 17 00:00:00 2001 From: stephenhensley Date: Fri, 1 Oct 2021 15:53:08 -0700 Subject: [PATCH 2/4] simplified pitch shifter, and fixed issues with negative tranposition. --- Source/Effects/pitchshifter.h | 85 +++++++++++------------------------ 1 file changed, 26 insertions(+), 59 deletions(-) diff --git a/Source/Effects/pitchshifter.h b/Source/Effects/pitchshifter.h index 82e97587..dd2f5be2 100644 --- a/Source/Effects/pitchshifter.h +++ b/Source/Effects/pitchshifter.h @@ -10,13 +10,6 @@ #include "Utility/delayline.h" #include "Control/phasor.h" -/** Shift can be 30-100 ms lets just start with 50 for now. -0.050 * SR = 2400 samples (at 48kHz) -*/ -#define SHIFT_BUFFER_SIZE 16384 -//#define SHIFT_BUFFER_SIZE 4800 -//#define SHIFT_BUFFER_SIZE 8192 -//#define SHIFT_BUFFER_SIZE 1024 namespace daisysp { @@ -49,7 +42,7 @@ t = 1 - ((s *f) / R) r is the sample_rate solving for t = 12.0 -f = (12 - 1) * 48000 / SHIFT_BUFFER_SIZE; +f = (12 - 1) * 48000 / kShiftDelaySize; \todo - move hash_xs32 and myrand to dsp.h and give appropriate names */ @@ -58,24 +51,22 @@ class PitchShifter public: PitchShifter() {} ~PitchShifter() {} - /** Initialize pitch shifter - */ - void Init(float sr) + /** Initialize pitch shifter */ + void Init(float sr, bool quantize_semitones = true) { force_recalc_ = false; sr_ = sr; mod_freq_ = 5.0f; - SetSemitones(); for(uint8_t i = 0; i < 2; i++) { gain_[i] = 0.0f; d_[i].Init(); phs_[i].Init(sr, 50, i == 0 ? 0 : PI_F); } - shift_up_ = true; - del_size_ = SHIFT_BUFFER_SIZE; + del_size_ = kShiftDelaySize; SetDelSize(del_size_); - fun_ = 0.0f; + fun_ = 0.0f; + quantize_semitones_ = quantize_semitones; } /** process pitch shifter @@ -104,13 +95,10 @@ class PitchShifter slewed_mod_[1] += mod_coeff_[1] * (mod_b_amt_ - slewed_mod_[1]); prev_phs_a_ = fade1; prev_phs_b_ = fade2; - if(shift_up_) - { - fade1 = 1.0f - fade1; - fade2 = 1.0f - fade2; - } - mod_[0] = fade1 * (del_size_ - 1); - mod_[1] = fade2 * (del_size_ - 1); + fade1 = 1.0f - fade1; + fade2 = 1.0f - fade2; + mod_[0] = fade1 * (del_size_ - 1); + mod_[1] = fade2 * (del_size_ - 1); #ifdef USE_ARM_DSP gain_[0] = arm_sin_f32(fade1 * (float)M_PI); gain_[1] = arm_sin_f32(fade2 * (float)M_PI); @@ -138,27 +126,12 @@ class PitchShifter */ void SetTransposition(const float &transpose) { - float ratio; - uint8_t idx; + float ratio; if(transpose_ != transpose || force_recalc_) { - transpose_ = transpose; - idx = (uint8_t)fabsf(transpose); - ratio = semitone_ratios_[idx % 12]; - ratio *= (uint8_t)(fabsf(transpose) / 12) + 1; - if(transpose > 0.0f) - { - shift_up_ = true; - } - else - { - shift_up_ = false; - } - mod_freq_ = ((ratio - 1.0f) * sr_) / del_size_; - if(mod_freq_ < 0.0f) - { - mod_freq_ = 0.0f; - } + transpose_ = quantize_semitones_ ? (int32_t)transpose : transpose; + ratio = pow(2.f, transpose_ / 12.f); + mod_freq_ = ((ratio - 1.0f) * sr_) / del_size_; phs_[0].SetFreq(mod_freq_); phs_[1].SetFreq(mod_freq_); if(force_recalc_) @@ -172,7 +145,7 @@ class PitchShifter */ void SetDelSize(uint32_t size) { - del_size_ = size < SHIFT_BUFFER_SIZE ? size : SHIFT_BUFFER_SIZE; + del_size_ = size < kShiftDelaySize ? size : kShiftDelaySize; force_recalc_ = true; SetTransposition(transpose_); } @@ -182,29 +155,23 @@ class PitchShifter inline void SetFun(float f) { fun_ = f; } private: - inline void SetSemitones() - { - for(size_t i = 0; i < 12; i++) - { - semitone_ratios_[i] = powf(2.0f, (float)i / 12); - } - } - typedef DelayLine ShiftDelay; - ShiftDelay d_[2]; - float pitch_shift_, mod_freq_; - uint32_t del_size_; - /** lfo stuff -*/ + /** Shift can be 30-100 ms lets just start with 50 for now. + 0.050 * SR = 2400 samples (at 48kHz) */ + static constexpr size_t kShiftDelaySize = 16384; + typedef DelayLine ShiftDelay; + ShiftDelay d_[2]; + float pitch_shift_, mod_freq_; + uint32_t del_size_; + /** lfo stuff */ bool force_recalc_; float sr_; - bool shift_up_; Phasor phs_[2]; float gain_[2], mod_[2], transpose_; float fun_, mod_a_amt_, mod_b_amt_, prev_phs_a_, prev_phs_b_; float slewed_mod_[2], mod_coeff_[2]; - /** pitch stuff -*/ - float semitone_ratios_[12]; + + /** Config stuff */ + bool quantize_semitones_; }; } // namespace daisysp From 56525c3ba298235fdda97c73f11e01da48e48d08 Mon Sep 17 00:00:00 2001 From: stephenhensley Date: Fri, 1 Oct 2021 15:59:38 -0700 Subject: [PATCH 3/4] changed quantize default to false, and added documentation for init. --- Source/Effects/pitchshifter.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Source/Effects/pitchshifter.h b/Source/Effects/pitchshifter.h index dd2f5be2..2ed58701 100644 --- a/Source/Effects/pitchshifter.h +++ b/Source/Effects/pitchshifter.h @@ -51,8 +51,13 @@ class PitchShifter public: PitchShifter() {} ~PitchShifter() {} - /** Initialize pitch shifter */ - void Init(float sr, bool quantize_semitones = true) + + + /** Initialize pitch shifter + * \param sr the expected samplerate in Hz of the audio engines + * \param quantize_semitones locks transpositions to integer values (defaults to false) + */ + void Init(float sr, bool quantize_semitones = false) { force_recalc_ = false; sr_ = sr; From 8fa08b13f92b12bcef1881373ab5a8ead8afc3b1 Mon Sep 17 00:00:00 2001 From: stephenhensley Date: Mon, 11 Oct 2021 11:05:56 -0700 Subject: [PATCH 4/4] fixed the 'fun' param to work the same when transposing below 0, and added some auto-recalc for transposition at/near zero. --- Source/Effects/pitchshifter.h | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/Source/Effects/pitchshifter.h b/Source/Effects/pitchshifter.h index 2ed58701..195fe620 100644 --- a/Source/Effects/pitchshifter.h +++ b/Source/Effects/pitchshifter.h @@ -76,20 +76,30 @@ class PitchShifter /** process pitch shifter */ - float Process(float &in) + float Process(float in) { float val, fade1, fade2; // First Process delay mod/crossfade - fade1 = phs_[0].Process(); - fade2 = phs_[1].Process(); - if(prev_phs_a_ > fade1) + fade1 = phs_[0].Process(); + fade2 = phs_[1].Process(); + bool recalc_a_fun = ((transpose_ >= 0.f) && (prev_phs_a_ > fade1)) + || ((transpose_ < 0.f) && prev_phs_a_ < fade1); + bool recalc_b_fun = ((transpose_ >= 0.f) && (prev_phs_b_ > fade2)) + || ((transpose_ < 0.f) && prev_phs_b_ < fade2); + // Randomly trigger mod recalc when tranpose is 0 so that the "fun" + // parameter still does something when not transposing + bool rand_retrig = (transpose_ >= -0.25f && transpose_ < 0.25f); + if(rand_retrig && fun_ > 0.f) + if(myrand() % 65536 < 4) + recalc_a_fun = recalc_b_fun = true; + if(recalc_a_fun) { mod_a_amt_ = fun_ * ((float)(myrand() % 255) / 255.0f) * (del_size_ * 0.5f); mod_coeff_[0] = 0.0002f + (((float)(myrand() % 255) / 255.0f) * 0.001f); } - if(prev_phs_b_ > fade2) + if(recalc_b_fun) { mod_b_amt_ = fun_ * ((float)(myrand() % 255) / 255.0f) * (del_size_ * 0.5f); @@ -116,9 +126,8 @@ class PitchShifter d_[0].Write(in); d_[1].Write(in); // Modulate Delay Lines - //mod_a_amt = mod_b_amt = 0.0f; - d_[0].SetDelay(mod_[0] + mod_a_amt_); - d_[1].SetDelay(mod_[1] + mod_b_amt_); + // d_[0].SetDelay(mod_[0] + mod_a_amt_); + // d_[1].SetDelay(mod_[1] + mod_b_amt_); d_[0].SetDelay(mod_[0] + slewed_mod_[0]); d_[1].SetDelay(mod_[1] + slewed_mod_[1]); val = 0.0f;