// ---- A simple linear falling envelope -------
class EnvelopeSimpleLinear {
  public:
    float counter = 1.0;
    float value;
    float speed = 0.001;
    float amount = 1.0;
    void update();
    void reset();
    void setAmount(float speed);
    void setSpeed(float speed);
};

void EnvelopeSimpleLinear::update() {
  this->counter -= this->speed;
  if (this->counter <= 0.0) {
    this->counter = 0.0;
  }
  this->value = this->counter * this->amount;
}

void EnvelopeSimpleLinear::reset() {
  this->counter = 1.0;
  this->value = 0.0;
}

void EnvelopeSimpleLinear::setSpeed(float speed) {
  this->speed = speed;
}

void EnvelopeSimpleLinear::setAmount(float amount) {
  this->amount = amount;
}

// ---- A simple logarithmic falling envelope -------
class EnvelopeSimpleLog {
  public:
    float counter = 1.0;
    float value;
    float speed = 0.001;
    float amount = 1.0;
    float snap = 0.005;
    void update();
    void reset();
    void setAmount(float speed);
    void setSpeed(float speed);
    void setSnap(float snap);
};

void EnvelopeSimpleLog::update() {
  this->counter -= this->speed;
  if (this->counter <= 0.0) {
    this->counter = 0.0;
  }
  this->value = max(0.0, (log10(this->snap + 1.0 - this->counter)*-1.0))/2.3 * this->amount;
}

void EnvelopeSimpleLog::reset() {
  this->counter = 1.0;
  this->value = 0.0;
}

void EnvelopeSimpleLog::setSpeed(float speed) {
  this->speed = speed;
}

void EnvelopeSimpleLog::setAmount(float amount) {
  this->amount = amount;
}

void EnvelopeSimpleLog::setSnap(float snap) {
  this->snap = snap;
}




// ---- A sigh envelope -------
class EnvelopeSigh {
  public:
    float counter = 0.0;
    float value;
    float speed = 0.001;
    float delay = 300;
    float amount = 1.0;
    double last_trigger;
    void update();
    void reset();
    void trigger();
    void setAmount(float speed);
    void setSpeed(float speed);
    void setDelay(float speed);
    void setSnap(float snap);
};

void EnvelopeSigh::update() {
  this->counter -= this->speed;
  if (this->counter <= 0.0) {
    this->counter = 0.0;
  }
  if ((millis() - this->last_trigger) > this->delay) {
    this->counter += this->speed;
    if (this->counter < 3.1415) {
      this->value = max(0.0, sin(this->counter)) * this->amount;
    } else {
      this->value = 0.0;
    }
  }
}

void EnvelopeSigh::trigger() {
  this->last_trigger = millis();
}

void EnvelopeSigh::reset() {
  this->counter = 1.0;
  this->value = 0.0;
}

void EnvelopeSigh::setSpeed(float speed) {
  this->speed = speed;
}

void EnvelopeSigh::setAmount(float amount) {
  this->amount = amount;
}

void EnvelopeSigh::setDelay(float delay) {
  this->delay = delay;
}