forked from electro-smith/DaisySP
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* compiling * allpass * freq conversion * crunch bug * still broke * add phaser to make and daisysp.h, remove phaser include paths * formatting * change phaser.h delayline include to relative path * fix phaser SetFreq clipping bug * move hz to deltime conversion to last second * add fonepole to mitigate lfo crunch around -1 * style to appease the robots * fixed init and replaced MAX POLES macro with internal static constexpr Co-authored-by: stephenhensley <stephen.p.hensley@gmail.com>
- Loading branch information
Showing
4 changed files
with
271 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,7 @@ decimator \ | |
flanger \ | ||
fold \ | ||
overdrive \ | ||
phaser \ | ||
reverbsc \ | ||
sampleratereducer \ | ||
tremolo | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
#include "dsp.h" | ||
#include "phaser.h" | ||
#include <math.h> | ||
|
||
using namespace daisysp; | ||
|
||
//PhaserEngine stuff | ||
void PhaserEngine::Init(float sample_rate) | ||
{ | ||
sample_rate_ = sample_rate; | ||
|
||
del_.Init(); | ||
lfo_amp_ = 0.f; | ||
feedback_ = .2f; | ||
SetFreq(200.f); | ||
|
||
del_.SetDelay(0.f); | ||
|
||
os_ = 30.f; //30 hertz frequency offset, lower than this introduces crunch | ||
deltime_ = 0.f; | ||
|
||
last_sample_ = 0.f; | ||
lfo_phase_ = 0.f; | ||
SetLfoFreq(.3); | ||
SetLfoDepth(.9); | ||
} | ||
|
||
float PhaserEngine::Process(float in) | ||
{ | ||
float lfo_sig = ProcessLfo(); | ||
fonepole(deltime_, sample_rate_ / (lfo_sig + ap_freq_ + os_), .0001f); | ||
|
||
last_sample_ = del_.Allpass(in + feedback_ * last_sample_, deltime_, .3f); | ||
|
||
return (in + last_sample_) * .5f; //equal mix | ||
} | ||
|
||
void PhaserEngine::SetLfoDepth(float depth) | ||
{ | ||
lfo_amp_ = fclamp(depth, 0.f, 1.f); | ||
} | ||
|
||
void PhaserEngine::SetLfoFreq(float lfo_freq) | ||
{ | ||
lfo_freq = 4.f * lfo_freq / sample_rate_; | ||
lfo_freq *= lfo_freq_ < 0.f ? -1.f : 1.f; //if we're headed down, keep going | ||
lfo_freq_ = fclamp(lfo_freq, -.25f, .25f); //clip at +/- .125 * sr | ||
} | ||
|
||
void PhaserEngine::SetFreq(float ap_freq) | ||
{ | ||
ap_freq_ = fclamp(ap_freq, 0.f, 20000.f); //0 - 20kHz | ||
} | ||
|
||
void PhaserEngine::SetFeedback(float feedback) | ||
{ | ||
feedback_ = fclamp(feedback, 0.f, .75f); | ||
} | ||
|
||
float PhaserEngine::ProcessLfo() | ||
{ | ||
lfo_phase_ += lfo_freq_; | ||
|
||
//wrap around and flip direction | ||
if(lfo_phase_ > 1.f) | ||
{ | ||
lfo_phase_ = 1.f - (lfo_phase_ - 1.f); | ||
lfo_freq_ *= -1.f; | ||
} | ||
else if(lfo_phase_ < -1.f) | ||
{ | ||
lfo_phase_ = -1.f - (lfo_phase_ + 1.f); | ||
lfo_freq_ *= -1.f; | ||
} | ||
|
||
return lfo_phase_ * lfo_amp_ * ap_freq_; | ||
} | ||
|
||
//Phaser Stuff | ||
void Phaser::Init(float sample_rate) | ||
{ | ||
for(size_t i = 0; i < kMaxPoles; i++) | ||
{ | ||
engines_[i].Init(sample_rate); | ||
} | ||
|
||
poles_ = 4; | ||
gain_frac_ = .5f; | ||
} | ||
|
||
float Phaser::Process(float in) | ||
{ | ||
float sig = 0.f; | ||
|
||
for(int i = 0; i < poles_; i++) | ||
{ | ||
sig += engines_[i].Process(in); | ||
} | ||
|
||
return sig; | ||
} | ||
|
||
void Phaser::SetPoles(int poles) | ||
{ | ||
poles_ = DSY_CLAMP(poles, 1, 8); | ||
} | ||
|
||
void Phaser::SetLfoDepth(float depth) | ||
{ | ||
for(int i = 0; i < kMaxPoles; i++) | ||
{ | ||
engines_[i].SetLfoDepth(depth); | ||
} | ||
} | ||
|
||
void Phaser::SetLfoFreq(float lfo_freq) | ||
{ | ||
for(int i = 0; i < kMaxPoles; i++) | ||
{ | ||
engines_[i].SetLfoFreq(lfo_freq); | ||
} | ||
} | ||
|
||
void Phaser::SetFreq(float ap_freq) | ||
{ | ||
for(int i = 0; i < kMaxPoles; i++) | ||
{ | ||
engines_[i].SetFreq(ap_freq); | ||
} | ||
} | ||
|
||
void Phaser::SetFeedback(float feedback) | ||
{ | ||
for(int i = 0; i < kMaxPoles; i++) | ||
{ | ||
engines_[i].SetFeedback(feedback); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#pragma once | ||
#ifndef DSY_PHASER_H | ||
#define DSY_PHASER_H | ||
#ifdef __cplusplus | ||
|
||
#include <stdint.h> | ||
#include "Utility/delayline.h" | ||
|
||
/** @file phaser.h */ | ||
|
||
namespace daisysp | ||
{ | ||
/** | ||
@brief Single Phaser engine. Used in Phaser. | ||
@author Ben Sergentanis | ||
*/ | ||
class PhaserEngine | ||
{ | ||
public: | ||
PhaserEngine() {} | ||
~PhaserEngine() {} | ||
|
||
/** Initialize the module | ||
\param sample_rate Audio engine sample rate. | ||
*/ | ||
void Init(float sample_rate); | ||
|
||
/** Get the next sample | ||
\param in Sample to process | ||
*/ | ||
float Process(float in); | ||
|
||
/** How much to modulate the allpass filter by. | ||
\param depth Works 0-1. | ||
*/ | ||
void SetLfoDepth(float depth); | ||
|
||
/** Set lfo frequency. | ||
\param lfo_freq Frequency in Hz | ||
*/ | ||
void SetLfoFreq(float lfo_freq); | ||
|
||
/** Set the allpass frequency | ||
\param ap_freq Frequency in Hz. | ||
*/ | ||
void SetFreq(float ap_freq); | ||
|
||
/** Set the feedback amount. | ||
\param feedback Amount from 0-1. | ||
*/ | ||
void SetFeedback(float feedback); | ||
|
||
private: | ||
float sample_rate_; | ||
static constexpr int32_t kDelayLength | ||
= 2400; // 50 ms at 48kHz = .05 * 48000 | ||
|
||
//triangle lfo | ||
float lfo_phase_; | ||
float lfo_freq_; | ||
float lfo_amp_; | ||
|
||
float os_; | ||
|
||
float feedback_; | ||
float ap_freq_; | ||
|
||
float deltime_; | ||
float last_sample_; | ||
|
||
DelayLine<float, kDelayLength> del_; | ||
|
||
float ProcessLfo(); | ||
}; | ||
|
||
//wraps up all of the phaser engines | ||
/** | ||
@brief Phaser Effect. | ||
@author Ben Sergentanis | ||
@date Jan 2021 | ||
*/ | ||
class Phaser | ||
{ | ||
public: | ||
Phaser() {} | ||
~Phaser() {} | ||
|
||
/** Initialize the module | ||
\param sample_rate Audio engine sample rate | ||
*/ | ||
void Init(float sample_rate); | ||
|
||
/** Get the next floating point sample. | ||
\param in Sample to process | ||
*/ | ||
float Process(float in); | ||
|
||
/** Number of allpass stages. | ||
\param poles Works 1 to 8. | ||
*/ | ||
void SetPoles(int poles); | ||
|
||
/** Set all lfo depths | ||
\param depth Works 0-1. | ||
*/ | ||
void SetLfoDepth(float depth); | ||
|
||
/** Set all lfo frequencies. | ||
\param lfo_freq Lfo freq in Hz. | ||
*/ | ||
void SetLfoFreq(float lfo_freq); | ||
|
||
/** Set all channel allpass freq in Hz. | ||
\param ap_freq Frequency in Hz. | ||
*/ | ||
void SetFreq(float ap_freq); | ||
|
||
/** Set all channels feedback. | ||
\param feedback Works 0-1. | ||
*/ | ||
void SetFeedback(float feedback); | ||
|
||
private: | ||
static constexpr int kMaxPoles = 8; | ||
PhaserEngine engines_[kMaxPoles]; | ||
float gain_frac_; | ||
int poles_; | ||
}; | ||
} //namespace daisysp | ||
#endif | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters