portemento, adsr

This commit is contained in:
michalcourson
2025-10-25 14:49:02 -04:00
parent 7ba141daed
commit d68a6d5c2a
12 changed files with 2121 additions and 1460 deletions

98
Source/adsr.h Normal file
View File

@ -0,0 +1,98 @@
/*
==============================================================================
adsr.h
Created: 25 Oct 2025 2:09:32pm
Author: mickl
==============================================================================
*/
#pragma once
#include <stdint.h>
/** Distinct stages that the phase of the envelope can be located in.
- IDLE = located at phase location 0, and not currently running
- ATTACK = First segment of envelope where phase moves from 0 to 1
- DECAY = Second segment of envelope where phase moves from 1 to SUSTAIN value
- RELEASE = Fourth segment of envelop where phase moves from SUSTAIN to 0
*/
enum
{
ADSR_SEG_IDLE = 0,
ADSR_SEG_ATTACK = 1,
ADSR_SEG_DECAY = 2,
ADSR_SEG_RELEASE = 4
};
/** adsr envelope module
Original author(s) : Paul Batchelor
Ported from Soundpipe by Ben Sergentanis, May 2020
Remake by Steffan DIedrichsen, May 2021
*/
class Adsr
{
public:
Adsr() {}
~Adsr() {}
/** Initializes the Adsr module.
\param sample_rate - The sample rate of the audio engine being run.
*/
void Init(float sample_rate, int blockSize = 1);
/**
\function Retrigger forces the envelope back to attack phase
\param hard resets the history to zero, results in a click.
*/
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
*/
void SetTime(int seg, float time);
void SetAttackTime(float timeInS, float shape = 0.0f);
void SetDecayTime(float timeInS);
void SetReleaseTime(float timeInS);
private:
void SetTimeConstant(float timeInS, float& time, float& coeff);
public:
/** Sustain level
\param sus_level - sets sustain level, 0...1.0
*/
inline void SetSustainLevel(float sus_level)
{
sus_level = (sus_level <= 0.f) ? -0.01f // forces envelope into idle
: (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.
*/
inline uint8_t GetCurrentSegment() { return mode_; }
/** Tells whether envelope is active
\return true if the envelope is currently in any stage apart from idle.
*/
inline bool IsRunning() const { return mode_ != ADSR_SEG_IDLE; }
private:
float sus_level_{ 0.f };
float x_{ 0.f };
float attackShape_{ -1.f };
float attackTarget_{ 0.0f };
float attackTime_{ -1.0f };
float decayTime_{ -1.0f };
float releaseTime_{ -1.0f };
float attackD0_{ 0.f };
float decayD0_{ 0.f };
float releaseD0_{ 0.f };
int sample_rate_;
uint8_t mode_{ ADSR_SEG_IDLE };
bool gate_{ false };
};