mirror of
https://github.com/TomHarte/CLK.git
synced 2024-09-13 20:55:40 +00:00
114 lines
3.1 KiB
C++
114 lines
3.1 KiB
C++
//
|
||
// EnvelopeGenerator.hpp
|
||
// Clock Signal
|
||
//
|
||
// Created by Thomas Harte on 01/05/2020.
|
||
// Copyright © 2020 Thomas Harte. All rights reserved.
|
||
//
|
||
|
||
#ifndef EnvelopeGenerator_h
|
||
#define EnvelopeGenerator_h
|
||
|
||
#include <optional>
|
||
#include <functional>
|
||
|
||
namespace Yamaha {
|
||
namespace OPL {
|
||
|
||
/*!
|
||
Models an OPL-style envelope generator.
|
||
|
||
Damping is optional; if damping is enabled then if there is a transition to key-on while
|
||
attenuation is less than maximum then attenuation will be quickly transitioned to maximum
|
||
before the attack phase can begin.
|
||
|
||
in real hardware damping is used by the envelope generators associated with
|
||
carriers, with phases being reset upon the transition from damping to attack.
|
||
|
||
This code considers application of tremolo to be a function of the envelope generator;
|
||
this is largely for logical conformity with the phase generator that necessarily has to
|
||
apply vibrato.
|
||
*/
|
||
template <int precision> class EnvelopeGenerator {
|
||
public:
|
||
/*!
|
||
Advances the envelope generator a single step, given the current state of the low-frequency oscillator, @c oscillator.
|
||
*/
|
||
void update(const LowFrequencyOscillator &oscillator);
|
||
|
||
/*!
|
||
@returns The current attenuation from this envelope generator.
|
||
*/
|
||
int attenuation() const;
|
||
|
||
/*!
|
||
Enables or disables damping on this envelope generator. If damping is enabled then this envelope generator will
|
||
use the damping phase when necessary (i.e. when transitioning to key on if attenuation is not already at maximum)
|
||
and in any case will call @c will_attack before transitioning from any other state to attack.
|
||
|
||
@param will_attack Supply a will_attack callback to enable damping mode; supply nullopt to disable damping mode.
|
||
*/
|
||
void set_should_damp(const std::optional<std::function<void(void)>> &will_attack);
|
||
|
||
/*!
|
||
Sets the current state of the key-on input.
|
||
*/
|
||
void set_key_on(bool);
|
||
|
||
/*!
|
||
Sets the attack rate, which should be in the range 0–15.
|
||
*/
|
||
void set_attack_rate(int);
|
||
|
||
/*!
|
||
Sets the decay rate, which should be in the range 0–15.
|
||
*/
|
||
void set_decay_rate(int);
|
||
|
||
/*!
|
||
Sets the release rate, which should be in the range 0–15.
|
||
*/
|
||
void set_release_rate(int);
|
||
|
||
/*!
|
||
Sets the sustain level, which should be in the range 0–15.
|
||
*/
|
||
void set_sustain_level(int);
|
||
|
||
/*!
|
||
Enables or disables use of the sustain level. If this is disabled, the envelope proceeds
|
||
directly from decay to release.
|
||
*/
|
||
void set_use_sustain_level(bool);
|
||
|
||
/*!
|
||
Enables or disables key-rate scaling.
|
||
*/
|
||
void set_key_rate_scaling_enabled(bool enabled);
|
||
|
||
/*!
|
||
Enables or disables application of the low-frequency oscillator's tremolo.
|
||
*/
|
||
void set_tremolo_enabled(bool enabled);
|
||
|
||
/*!
|
||
Sets the current period associated with the channel that owns this envelope generator;
|
||
this is used to select a key scaling rate if key-rate scaling is enabled.
|
||
*/
|
||
void set_period(int period, int octave);
|
||
|
||
private:
|
||
enum class ADSRPhase {
|
||
Attack, Decay, Sustain, Release, Damp
|
||
} adsr_phase_ = ADSRPhase::Attack;
|
||
int adsr_attenuation_ = 511;
|
||
|
||
bool key_on_ = false;
|
||
std::optional<std::function<void(void)>> will_attack_;
|
||
};
|
||
|
||
}
|
||
}
|
||
|
||
#endif /* EnvelopeGenerator_h */
|