// Copyright 2009 Olivier Gillet.
//
// Author: Olivier Gillet (ol.gillet@gmail.com)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// -----------------------------------------------------------------------------
//
// Envelopes.
#ifndef SHRUTHI_ENVELOPE_H_
#define SHRUTHI_ENVELOPE_H_
#include "avrlib/base.h"
#include "shruthi/patch.h"
#include "shruthi/resources.h"
#include "shruthi/shruthi.h"
#include "avrlib/op.h"
using namespace avrlib;
namespace shruthi {
enum EnvelopeStage {
ATTACK = 0,
DECAY = 1,
SUSTAIN = 2,
RELEASE = 3,
DEAD = 4,
NUM_SEGMENTS,
};
class Envelope {
public:
Envelope() { }
void Init() {
stage_target_[ATTACK] = 255;
stage_target_[RELEASE] = 0;
stage_target_[DEAD] = 0;
stage_phase_increment_[SUSTAIN] = 0;
stage_phase_increment_[DEAD] = 0;
}
uint8_t stage() { return stage_; }
uint16_t value() { return value_; }
void Trigger(uint8_t stage) {
if (stage == DEAD) {
value_ = 0;
}
a_ = value_ >> 8;
b_ = stage_target_[stage];
stage_ = stage;
phase_ = 0;
phase_increment_ = stage_phase_increment_[stage];
}
inline void UpdateAttack(uint8_t attack) {
stage_phase_increment_[ATTACK] = ResourcesManager::Lookup<
uint16_t, uint8_t>(lut_res_env_portamento_increments, attack);
phase_increment_ = stage_phase_increment_[stage_];
}
inline void Update(
uint8_t attack,
uint8_t decay,
uint8_t sustain,
uint8_t release) {
stage_phase_increment_[ATTACK] = ResourcesManager::Lookup<
uint16_t, uint8_t>(lut_res_env_portamento_increments, attack);
stage_phase_increment_[DECAY] = ResourcesManager::Lookup<
uint16_t, uint8_t>(lut_res_env_portamento_increments, decay);
stage_phase_increment_[RELEASE] = ResourcesManager::Lookup<
uint16_t, uint8_t>(lut_res_env_portamento_increments, release);
stage_target_[DECAY] = sustain << 1;
stage_target_[SUSTAIN] = stage_target_[DECAY];
}
uint8_t Render() {
phase_ += phase_increment_;
if (phase_ < phase_increment_) {
value_ = U8MixU16(a_, b_, 255);
Trigger(++stage_);
}
if (phase_increment_) {
uint8_t step = InterpolateSample(wav_res_env_expo, phase_);
value_ = U8MixU16(a_, b_, step);
}
return stage_ == SUSTAIN ? stage_target_[DECAY] : value_ >> 8;
}
private:
// Phase increments for each stage.
uint16_t stage_phase_increment_[NUM_SEGMENTS];
// Value that needs to be reached at the end of each stage.
uint8_t stage_target_[NUM_SEGMENTS];
// Current stage.
uint8_t stage_;
// Start and end value of the current segment.
uint8_t a_;
uint8_t b_;
// Phase and phase increment.
uint16_t phase_increment_;
uint16_t phase_;
// Current value of the envelope.
uint16_t value_;
DISALLOW_COPY_AND_ASSIGN(Envelope);
};
} // namespace shruthi
#endif // SHRUTHI_ENVELOPE_H_
const prog_uint8_t wav_res_env_expo[] PROGMEM = {
0, 4, 9, 14, 19, 23, 28, 32,
37, 41, 45, 49, 53, 57, 61, 65,
68, 72, 76, 79, 83, 86, 89, 92,
96, 99, 102, 105, 108, 111, 113, 116,
119, 121, 124, 127, 129, 132, 134, 136,
139, 141, 143, 145, 148, 150, 152, 154,
156, 158, 160, 161, 163, 165, 167, 169,
170, 172, 174, 175, 177, 178, 180, 181,
183, 184, 186, 187, 188, 190, 191, 192,
193, 195, 196, 197, 198, 199, 200, 201,
202, 203, 205, 206, 206, 207, 208, 209,
210, 211, 212, 213, 214, 215, 215, 216,
217, 218, 218, 219, 220, 221, 221, 222,
223, 223, 224, 225, 225, 226, 226, 227,
227, 228, 229, 229, 230, 230, 231, 231,
232, 232, 233, 233, 233, 234, 234, 235,
235, 236, 236, 236, 237, 237, 238, 238,
238, 239, 239, 239, 240, 240, 240, 241,
241, 241, 241, 242, 242, 242, 243, 243,
243, 243, 244, 244, 244, 244, 245, 245,
245, 245, 245, 246, 246, 246, 246, 246,
247, 247, 247, 247, 247, 248, 248, 248,
248, 248, 248, 248, 249, 249, 249, 249,
249, 249, 249, 250, 250, 250, 250, 250,
250, 250, 250, 251, 251, 251, 251, 251,
251, 251, 251, 251, 251, 252, 252, 252,
252, 252, 252, 252, 252, 252, 252, 252,
252, 253, 253, 253, 253, 253, 253, 253,
253, 253, 253, 253, 253, 253, 253, 253,
253, 254, 254, 254, 254, 254, 254, 254,
254, 254, 254, 254, 254, 254, 254, 254,
254, 254, 254, 254, 254, 254, 254, 255,
255,
};