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

Adsr remake #160

Merged
merged 25 commits into from
Jun 4, 2021
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e31062c
Add block size to Init() for block based processing
sdiedrichsen May 16, 2021
9270e02
Remove unused variables
sdiedrichsen May 16, 2021
6cef9df
Add improved SetTime method
sdiedrichsen May 16, 2021
0815c36
Redo processing with 1st order SVF
sdiedrichsen May 16, 2021
fd2c01f
remove unused methods
sdiedrichsen May 16, 2021
0694188
Clamp sustain level
sdiedrichsen May 16, 2021
f6be712
Fix Init()
sdiedrichsen May 16, 2021
38518ba
Add method for retrigger
sdiedrichsen May 16, 2021
040dfc6
Avoid div by zero
sdiedrichsen May 16, 2021
0e68e83
Some formatting
sdiedrichsen May 16, 2021
081c2d9
Optimize coefficient calculation
sdiedrichsen May 17, 2021
62f85fd
Fix unwanted repetition
sdiedrichsen May 17, 2021
2b0a313
Fix warning about missing inline function
sdiedrichsen May 17, 2021
5a38516
Sign my work
sdiedrichsen May 17, 2021
b8add11
Conform to clang format
sdiedrichsen May 19, 2021
3f32d15
Conform to clang format
sdiedrichsen May 19, 2021
f81af3e
Fix a typo
sdiedrichsen May 19, 2021
4605250
Conform to flag format pt. 2.
sdiedrichsen May 19, 2021
cf72a88
Conform to clang format pt.3
sdiedrichsen May 19, 2021
b45d50e
Clang Format pt.4
sdiedrichsen May 19, 2021
ebbd1c2
Checked with local clang, no issues
sdiedrichsen May 19, 2021
21259f1
Conform to clang format pt.5
sdiedrichsen May 20, 2021
4b06a79
Remove very white space
sdiedrichsen May 20, 2021
8e606fa
Attack with shape added, some refinements
sdiedrichsen May 24, 2021
3d84eca
Conform to clang-format
sdiedrichsen May 25, 2021
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
88 changes: 43 additions & 45 deletions Source/Control/adsr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,79 +3,77 @@

using namespace daisysp;

float Adsr::Tau2Pole(float tau)

void Adsr::Init(float sample_rate, int blockSize)
{
return expf(-1.0f / (tau * sample_rate_));
sample_rate_ = sample_rate / blockSize;
SetTime(ADSR_SEG_ATTACK, 0.1f);
SetTime(ADSR_SEG_DECAY, 0.1f);
SetTime(ADSR_SEG_RELEASE, 0.1f);
sus_level_ = 0.7f;
x_ = 0.0f;
}

float Adsr::AdsrFilter()
void Adsr::Retrigger(bool hard)
{
y_ = b_ * x_ + a_ * y_;
return y_;
mode_ = ADSR_SEG_ATTACK;
if(hard)
x_ = 0.f;
}


void Adsr::Init(float sample_rate)
void
Adsr::SetTime(int seg, float time)
{
seg_time_[ADSR_SEG_ATTACK] = 0.1f;
seg_time_[ADSR_SEG_DECAY] = 0.1f;
sus_ = 0.7f;
seg_time_[ADSR_SEG_RELEASE] = 0.1f;
//timer_ = 0;
a_ = 0.0f;
b_ = 0.0f;
x_ = 0.0f;
y_ = 0.0f;
prev_ = 0.0f;
atk_time_ = seg_time_[ADSR_SEG_ATTACK] * sample_rate;
sample_rate_ = sample_rate;
if(seg_time_[seg] != time)
{
seg_time_[seg] = time;
if(time > 0.f)
{
const float attackTarget = logf(0.5f);
const float decayTarget = logf(1./M_E);
float target = (seg == ADSR_SEG_ATTACK)? attackTarget : decayTarget;
seg_D0_ [seg] = 1.f - expf(target / (time * sample_rate_));
}
else
seg_D0_ [seg] = 1.f; // instant change
}
}


float Adsr::Process(bool gate)
{
float pole, out;
out = 0.0f;
float out = 0.0f;

if(gate && mode_ != ADSR_SEG_DECAY)
{
mode_ = ADSR_SEG_ATTACK;
//timer_ = 0;
pole = Tau2Pole(seg_time_[ADSR_SEG_ATTACK] * 0.6f);
atk_time_ = seg_time_[ADSR_SEG_ATTACK] * sample_rate_;
a_ = pole;
b_ = 1.0f - pole;
}
else if(!gate && mode_ != ADSR_SEG_IDLE)
{
mode_ = ADSR_SEG_RELEASE;
pole = Tau2Pole(seg_time_[ADSR_SEG_RELEASE]);
a_ = pole;
b_ = 1.0f - pole;
}

x_ = (int)gate;
prev_ = (int)gate;

float D0(seg_D0_[mode_]);
float target = mode_ == ADSR_SEG_DECAY? sus_level_ : - 0.1f;
sdiedrichsen marked this conversation as resolved.
Show resolved Hide resolved
switch(mode_)
{
case ADSR_SEG_IDLE: out = 0.0f; break;
case ADSR_SEG_ATTACK:
out = AdsrFilter();

if(out > .99f)
x_ += D0 * (2.f - x_);
sdiedrichsen marked this conversation as resolved.
Show resolved Hide resolved
out = x_;
if(out > 1.f)
{
x_ =
out = 1.f;
sdiedrichsen marked this conversation as resolved.
Show resolved Hide resolved
mode_ = ADSR_SEG_DECAY;
pole = Tau2Pole(seg_time_[ADSR_SEG_DECAY]);
a_ = pole;
b_ = 1.0f - pole;
}
break;
case ADSR_SEG_DECAY:
case ADSR_SEG_RELEASE:
x_ *= sus_;
out = AdsrFilter();
if(out <= 0.01f)
x_ += D0 * (target - x_);
out = x_;
if(out < 0.0f)
sdiedrichsen marked this conversation as resolved.
Show resolved Hide resolved
{
x_ =
out = 0.f;
mode_ = ADSR_SEG_IDLE;
}
default: break;
}
return out;
Expand Down
31 changes: 23 additions & 8 deletions Source/Control/adsr.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,45 @@ enum
Original author(s) : Paul Batchelor
sdiedrichsen marked this conversation as resolved.
Show resolved Hide resolved

Ported from Soundpipe by Ben Sergentanis, May 2020

Remake by Steffan DIedrichsen, May 2021
*/
class Adsr
{
public:
Adsr() {}
Adsr () {}
sdiedrichsen marked this conversation as resolved.
Show resolved Hide resolved
~Adsr() {}
/** Initializes the Adsr module.
\param sample_rate - The sample rate of the audio engine being run.
*/
void Init(float sample_rate);
void Init(float sample_rate, int blockSize = 1);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a comment line about blockSize in the above comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.


/**
\function Retrigger forces the envelope back to attack phase
\param hard resets the hosrory to zero, results in a click.
sdiedrichsen marked this conversation as resolved.
Show resolved Hide resolved
*/

void Retrigger(bool hard);


/** Processes one sample through the filter and returns one sample.
\param gate - trigger the envelope, hold it to sustain
*/

float Process(bool gate);

/** Sets time
Set time per segment in seconds
*/
inline void SetTime(int seg, float time) { seg_time_[seg] = time; }
void SetTime(int seg, float time);
sdiedrichsen marked this conversation as resolved.
Show resolved Hide resolved
/** Sustain level
\param sus_level - sets sustain level
\param sus_level - sets sustain level, 0...1.0
*/
inline void SetSustainLevel(float sus_level) { sus_ = sus_level; }
inline void SetSustainLevel(float sus_level)
{
sus_level = (sus_level < 0.f)? 0.f : (sus_level > 1.f)? 1.f : sus_level;
sus_level_ = sus_level;
}
/** get the current envelope segment
\return the segment of the envelope that the phase is currently located in.
*/
Expand All @@ -66,11 +80,12 @@ class Adsr
inline bool IsRunning() const { return mode_ != ADSR_SEG_IDLE; }

private:
float sus_, seg_time_[ADSR_SEG_LAST], a_, b_, y_, x_, prev_, atk_time_;
float sus_level_,
seg_time_[ADSR_SEG_LAST]{0.f},
sdiedrichsen marked this conversation as resolved.
Show resolved Hide resolved
seg_D0_[ADSR_SEG_LAST]{0.f},
x_;
int sample_rate_;
uint8_t mode_;
float Tau2Pole(float tau);
float AdsrFilter();
};
} // namespace daisysp
#endif
Expand Down