You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
2.9 KiB

4 years ago
#pragma once
#ifndef ADENV_H
#define ADENV_H
#include <stdint.h>
#ifdef __cplusplus
namespace daisysp
{
/** Distinct stages that the phase of the envelope can be located in.
@see AdEnv
*/
enum AdEnvSegment
{
/** located at phase location 0, and not currently running */
ADENV_SEG_IDLE,
/** First segment of envelope where phase moves from MIN value to MAX value */
ADENV_SEG_ATTACK,
/** Second segment of envelope where phase moves from MAX to MIN value */
ADENV_SEG_DECAY,
/** The final segment of the envelope (currently decay) */
ADENV_SEG_LAST,
};
/** Trigger-able envelope with adjustable min/max, and independent per-segment time control.
\author shensley
\todo - Add Cycling
\todo - Implement Curve (its only linear for now).
\todo - Maybe make this an ADsr_ that has AD/AR/Asr_ modes.
*/
class AdEnv
{
public:
AdEnv() {}
~AdEnv() {}
/** Initializes the ad envelope.
Defaults:
- current segment = idle
- curve = linear
- phase = 0
- min = 0
- max = 1
\param sample_rate sample rate of the audio engine being run
*/
void Init(float sample_rate);
/** Processes the current sample of the envelope. This should be called once
per sample period.
\return the current envelope value.
*/
float Process();
/** Starts or retriggers the envelope.*/
inline void Trigger() { trigger_ = 1; }
/** Sets the length of time (in seconds) for a specific segment. */
inline void SetTime(uint8_t seg, float time) { segment_time_[seg] = time; }
/** Sets the amount of curve applied. A positve value will create a log
curve. Input range: -100 to 100. (or more)
*/
inline void SetCurve(float scalar) { curve_scalar_ = scalar; }
/** Sets the minimum value of the envelope output.
Input range: -FLTmax_, to FLTmax_
*/
inline void SetMin(float min) { min_ = min; }
/** Sets the maximum value of the envelope output.
Input range: -FLTmax_, to FLTmax_
*/
inline void SetMax(float max) { max_ = max; }
/** Returns the current output value without processing the next sample */
inline float GetValue() const { return (output_ * (max_ - min_)) + min_; }
/** Returns the segment of the envelope that the phase is currently located
in.
*/
inline uint8_t GetCurrentSegment() { return current_segment_; }
/** Returns true if the envelope is currently in any stage apart from idle.
*/
inline bool IsRunning() const { return current_segment_ != ADENV_SEG_IDLE; }
private:
uint8_t current_segment_, prev_segment_;
float segment_time_[ADENV_SEG_LAST];
float sample_rate_, min_, max_, output_, curve_scalar_;
float c_inc_, curve_x_, retrig_val_;
uint32_t phase_;
uint8_t trigger_;
};
} // namespace daisysp
#endif
#endif