DaisySP
Loading...
Searching...
No Matches
pitchshifter.h
1/*
2Copyright (c) 2020 Electrosmith, Corp
3
4Use of this source code is governed by an MIT-style
5license that can be found in the LICENSE file or at
6https://opensource.org/licenses/MIT.
7*/
8
9#pragma once
10#ifndef DSY_PITCHSHIFTER_H
11#define DSY_PITCHSHIFTER_H
12#include <stdint.h>
13#include <cmath>
14#ifdef USE_ARM_DSP
15#include "arm_math.h"
16#endif
17#include "Utility/dsp.h"
18#include "Utility/delayline.h"
19#include "Control/phasor.h"
20
24#define SHIFT_BUFFER_SIZE 16384
25//#define SHIFT_BUFFER_SIZE 4800
26//#define SHIFT_BUFFER_SIZE 8192
27//#define SHIFT_BUFFER_SIZE 1024
28
29namespace daisysp
30{
31static inline uint32_t hash_xs32(uint32_t x)
32{
33 x ^= x << 13;
34 x ^= x >> 17;
35 x ^= x << 5;
36 return x;
37}
38
39inline uint32_t myrand()
40{
41 static uint32_t seed = 1;
42 seed = hash_xs32(seed);
43 return seed;
44}
45
65{
66 public:
67 PitchShifter() {}
68 ~PitchShifter() {}
71 void Init(float sr)
72 {
73 force_recalc_ = false;
74 sr_ = sr;
75 mod_freq_ = 5.0f;
76 SetSemitones();
77 for(uint8_t i = 0; i < 2; i++)
78 {
79 gain_[i] = 0.0f;
80 d_[i].Init();
81 phs_[i].Init(sr, 50, i == 0 ? 0 : PI_F);
82 }
83 shift_up_ = true;
84 del_size_ = SHIFT_BUFFER_SIZE;
85 SetDelSize(del_size_);
86 fun_ = 0.0f;
87 }
88
91 float Process(float &in)
92 {
93 float val, fade1, fade2;
94 // First Process delay mod/crossfade
95 fade1 = phs_[0].Process();
96 fade2 = phs_[1].Process();
97 if(prev_phs_a_ > fade1)
98 {
99 mod_a_amt_ = fun_ * ((float)(myrand() % 255) / 255.0f)
100 * (del_size_ * 0.5f);
101 mod_coeff_[0]
102 = 0.0002f + (((float)(myrand() % 255) / 255.0f) * 0.001f);
103 }
104 if(prev_phs_b_ > fade2)
105 {
106 mod_b_amt_ = fun_ * ((float)(myrand() % 255) / 255.0f)
107 * (del_size_ * 0.5f);
108 mod_coeff_[1]
109 = 0.0002f + (((float)(myrand() % 255) / 255.0f) * 0.001f);
110 }
111 slewed_mod_[0] += mod_coeff_[0] * (mod_a_amt_ - slewed_mod_[0]);
112 slewed_mod_[1] += mod_coeff_[1] * (mod_b_amt_ - slewed_mod_[1]);
113 prev_phs_a_ = fade1;
114 prev_phs_b_ = fade2;
115 if(shift_up_)
116 {
117 fade1 = 1.0f - fade1;
118 fade2 = 1.0f - fade2;
119 }
120 mod_[0] = fade1 * (del_size_ - 1);
121 mod_[1] = fade2 * (del_size_ - 1);
122#ifdef USE_ARM_DSP
123 gain_[0] = arm_sin_f32(fade1 * (float)M_PI);
124 gain_[1] = arm_sin_f32(fade2 * (float)M_PI);
125#else
126 gain_[0] = sinf(fade1 * PI_F);
127 gain_[1] = sinf(fade2 * PI_F);
128#endif
129
130 // Handle Delay Writing
131 d_[0].Write(in);
132 d_[1].Write(in);
133 // Modulate Delay Lines
134 //mod_a_amt = mod_b_amt = 0.0f;
135 d_[0].SetDelay(mod_[0] + mod_a_amt_);
136 d_[1].SetDelay(mod_[1] + mod_b_amt_);
137 d_[0].SetDelay(mod_[0] + slewed_mod_[0]);
138 d_[1].SetDelay(mod_[1] + slewed_mod_[1]);
139 val = 0.0f;
140 val += (d_[0].Read() * gain_[0]);
141 val += (d_[1].Read() * gain_[1]);
142 return val;
143 }
144
147 void SetTransposition(const float &transpose)
148 {
149 float ratio;
150 uint8_t idx;
151 if(transpose_ != transpose || force_recalc_)
152 {
153 transpose_ = transpose;
154 idx = (uint8_t)fabsf(transpose);
155 ratio = semitone_ratios_[idx % 12];
156 ratio *= (uint8_t)(fabsf(transpose) / 12) + 1;
157 if(transpose > 0.0f)
158 {
159 shift_up_ = true;
160 }
161 else
162 {
163 shift_up_ = false;
164 }
165 mod_freq_ = ((ratio - 1.0f) * sr_) / del_size_;
166 if(mod_freq_ < 0.0f)
167 {
168 mod_freq_ = 0.0f;
169 }
170 phs_[0].SetFreq(mod_freq_);
171 phs_[1].SetFreq(mod_freq_);
172 if(force_recalc_)
173 {
174 force_recalc_ = false;
175 }
176 }
177 }
178
181 void SetDelSize(uint32_t size)
182 {
183 del_size_ = size < SHIFT_BUFFER_SIZE ? size : SHIFT_BUFFER_SIZE;
184 force_recalc_ = true;
185 SetTransposition(transpose_);
186 }
187
190 inline void SetFun(float f) { fun_ = f; }
191
192 private:
193 inline void SetSemitones()
194 {
195 for(size_t i = 0; i < 12; i++)
196 {
197 semitone_ratios_[i] = powf(2.0f, (float)i / 12);
198 }
199 }
200 typedef DelayLine<float, SHIFT_BUFFER_SIZE> ShiftDelay;
201 ShiftDelay d_[2];
202 float pitch_shift_, mod_freq_;
203 uint32_t del_size_;
206 bool force_recalc_;
207 float sr_;
208 bool shift_up_;
209 Phasor phs_[2];
210 float gain_[2], mod_[2], transpose_;
211 float fun_, mod_a_amt_, mod_b_amt_, prev_phs_a_, prev_phs_b_;
212 float slewed_mod_[2], mod_coeff_[2];
215 float semitone_ratios_[12];
216};
217} // namespace daisysp
218
219#endif
void SetDelay(size_t delay)
Definition delayline.h:51
const T Read() const
Definition delayline.h:78
void Write(const T sample)
Definition delayline.h:70
void Init()
Definition delayline.h:35
float Process()
Definition phasor.cpp:13
void SetFreq(float freq)
Definition phasor.cpp:7
void Init(float sample_rate, float freq, float initial_phase)
Definition phasor.h:34
Definition pitchshifter.h:65
void Init(float sr)
Definition pitchshifter.h:71
void SetTransposition(const float &transpose)
Definition pitchshifter.h:147
float Process(float &in)
Definition pitchshifter.h:91
void SetDelSize(uint32_t size)
Definition pitchshifter.h:181
void SetFun(float f)
Definition pitchshifter.h:190
FIR Filter implementation, generic and ARM CMSIS DSP based.
Definition adenv.h:16