Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/pitch shift #166

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Source/Control/phasor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ float Phasor::Process()
}
if(phs_ < 0.0f)
{
phs_ = 0.0f;
phs_ += TWOPI_F;
}
return out;
}
113 changes: 47 additions & 66 deletions Source/Effects/pitchshifter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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
*/
Expand All @@ -58,42 +51,55 @@ class PitchShifter
public:
PitchShifter() {}
~PitchShifter() {}
/** Initialize pitch shifter


/** 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)
void Init(float sr, bool quantize_semitones = false)
{
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
*/
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);
Expand All @@ -104,13 +110,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);
Expand All @@ -123,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;
Expand All @@ -138,27 +140,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_)
Expand All @@ -172,7 +159,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_);
}
Expand All @@ -182,29 +169,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<float, SHIFT_BUFFER_SIZE> 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<float, kShiftDelaySize> 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

Expand Down