AR Envelope Generator

Dependencies:   mbed

Committer:
ryood
Date:
Tue Aug 15 13:52:49 2017 +0000
Revision:
0:a08920b1cb6d
AR Envelope Generator.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ryood 0:a08920b1cb6d 1 /*
ryood 0:a08920b1cb6d 2 * Nucleo F446 内蔵DACでエンベロープ波形発生
ryood 0:a08920b1cb6d 3 *
ryood 0:a08920b1cb6d 4 * 2017.08.14
ryood 0:a08920b1cb6d 5 *
ryood 0:a08920b1cb6d 6 */
ryood 0:a08920b1cb6d 7
ryood 0:a08920b1cb6d 8 #include "mbed.h"
ryood 0:a08920b1cb6d 9
ryood 0:a08920b1cb6d 10 #define UART_TRACE (0)
ryood 0:a08920b1cb6d 11 #define TITLE_STR1 ("Envelope Generator")
ryood 0:a08920b1cb6d 12 #define TITLE_STR2 ("20170814")
ryood 0:a08920b1cb6d 13
ryood 0:a08920b1cb6d 14 #define PI_F (3.1415926f)
ryood 0:a08920b1cb6d 15 #define SAMPLING_RATE (48000)
ryood 0:a08920b1cb6d 16 #define SAMPLING_PERIOD (1.0f/SAMPLING_RATE)
ryood 0:a08920b1cb6d 17 #define ENVELOPE_UPDATE_RATE SAMPLING_RATE
ryood 0:a08920b1cb6d 18
ryood 0:a08920b1cb6d 19 AnalogOut Dac1(PA_4);
ryood 0:a08920b1cb6d 20
ryood 0:a08920b1cb6d 21 class EnvelopeAR
ryood 0:a08920b1cb6d 22 {
ryood 0:a08920b1cb6d 23 public:
ryood 0:a08920b1cb6d 24 EnvelopeAR(int _attack, int _release, float _v0, float _v1, float _v2, float _attackTauRatio=0.36f, float _releaseTauRatio=0.36f) :
ryood 0:a08920b1cb6d 25 amplitude(_v0),
ryood 0:a08920b1cb6d 26 v0(_v0),
ryood 0:a08920b1cb6d 27 v1(_v1),
ryood 0:a08920b1cb6d 28 v2(_v2),
ryood 0:a08920b1cb6d 29 vLast(_v0),
ryood 0:a08920b1cb6d 30 attackTauRatio(_attackTauRatio),
ryood 0:a08920b1cb6d 31 releaseTauRatio(_releaseTauRatio) {
ryood 0:a08920b1cb6d 32 setAttack(_attack);
ryood 0:a08920b1cb6d 33 setRelease(_release);
ryood 0:a08920b1cb6d 34 }
ryood 0:a08920b1cb6d 35
ryood 0:a08920b1cb6d 36 ~EnvelopeAR() {}
ryood 0:a08920b1cb6d 37
ryood 0:a08920b1cb6d 38 void setAttack(int _attack) {
ryood 0:a08920b1cb6d 39 attack = _attack;
ryood 0:a08920b1cb6d 40 tau0 = attack * attackTauRatio;
ryood 0:a08920b1cb6d 41 }
ryood 0:a08920b1cb6d 42 int getAttack() {
ryood 0:a08920b1cb6d 43 return attack;
ryood 0:a08920b1cb6d 44 }
ryood 0:a08920b1cb6d 45
ryood 0:a08920b1cb6d 46 void setRelease(int _release) {
ryood 0:a08920b1cb6d 47 release = _release;
ryood 0:a08920b1cb6d 48 tau1 = release * releaseTauRatio;
ryood 0:a08920b1cb6d 49 }
ryood 0:a08920b1cb6d 50 int getRelease() {
ryood 0:a08920b1cb6d 51 return release;
ryood 0:a08920b1cb6d 52 }
ryood 0:a08920b1cb6d 53
ryood 0:a08920b1cb6d 54 void setAttackTauRatio(float _attackTauRatio) {
ryood 0:a08920b1cb6d 55 attackTauRatio = _attackTauRatio;
ryood 0:a08920b1cb6d 56 tau0 = attack * attackTauRatio;
ryood 0:a08920b1cb6d 57 }
ryood 0:a08920b1cb6d 58 float getAttackTauRatio() {
ryood 0:a08920b1cb6d 59 return attackTauRatio;
ryood 0:a08920b1cb6d 60 }
ryood 0:a08920b1cb6d 61
ryood 0:a08920b1cb6d 62 void setReleaseTauRatio(float _releaseTauRatio) {
ryood 0:a08920b1cb6d 63 releaseTauRatio = _releaseTauRatio;
ryood 0:a08920b1cb6d 64 tau1 = release * releaseTauRatio;
ryood 0:a08920b1cb6d 65 }
ryood 0:a08920b1cb6d 66 float getReleaseTauRatio() {
ryood 0:a08920b1cb6d 67 return releaseTauRatio;
ryood 0:a08920b1cb6d 68 }
ryood 0:a08920b1cb6d 69
ryood 0:a08920b1cb6d 70 float getTau0() {
ryood 0:a08920b1cb6d 71 return tau0;
ryood 0:a08920b1cb6d 72 }
ryood 0:a08920b1cb6d 73 float getTau1() {
ryood 0:a08920b1cb6d 74 return tau1;
ryood 0:a08920b1cb6d 75 }
ryood 0:a08920b1cb6d 76
ryood 0:a08920b1cb6d 77 void setV0(float _v0) {
ryood 0:a08920b1cb6d 78 v0 = _v0;
ryood 0:a08920b1cb6d 79 }
ryood 0:a08920b1cb6d 80 float getV0() {
ryood 0:a08920b1cb6d 81 return v0;
ryood 0:a08920b1cb6d 82 }
ryood 0:a08920b1cb6d 83 void setV1(float _v1) {
ryood 0:a08920b1cb6d 84 v1 = _v1;
ryood 0:a08920b1cb6d 85 }
ryood 0:a08920b1cb6d 86 float getV1() {
ryood 0:a08920b1cb6d 87 return v1;
ryood 0:a08920b1cb6d 88 }
ryood 0:a08920b1cb6d 89 void setV2(float _v2) {
ryood 0:a08920b1cb6d 90 v2 = _v2;
ryood 0:a08920b1cb6d 91 }
ryood 0:a08920b1cb6d 92 float getV2() {
ryood 0:a08920b1cb6d 93 return v2;
ryood 0:a08920b1cb6d 94 }
ryood 0:a08920b1cb6d 95
ryood 0:a08920b1cb6d 96 float getAmplitude() {
ryood 0:a08920b1cb6d 97 return amplitude;
ryood 0:a08920b1cb6d 98 }
ryood 0:a08920b1cb6d 99 float getAmplitude(int tick) {
ryood 0:a08920b1cb6d 100 if (tick < attack) {
ryood 0:a08920b1cb6d 101 // attackの処理
ryood 0:a08920b1cb6d 102 amplitude = v0 + (v1 - v0) * (1 - expf(-(float)tick / tau0));
ryood 0:a08920b1cb6d 103 vLast = amplitude;
ryood 0:a08920b1cb6d 104 } else {
ryood 0:a08920b1cb6d 105 // releaseの処理
ryood 0:a08920b1cb6d 106 amplitude = (vLast - v2) * (expf(-(float)(tick - attack) / tau1)) + v2;
ryood 0:a08920b1cb6d 107 }
ryood 0:a08920b1cb6d 108 return amplitude;
ryood 0:a08920b1cb6d 109 }
ryood 0:a08920b1cb6d 110
ryood 0:a08920b1cb6d 111 private:
ryood 0:a08920b1cb6d 112 int attack;
ryood 0:a08920b1cb6d 113 int release;
ryood 0:a08920b1cb6d 114 float amplitude;
ryood 0:a08920b1cb6d 115 float v0;
ryood 0:a08920b1cb6d 116 float v1;
ryood 0:a08920b1cb6d 117 float v2;
ryood 0:a08920b1cb6d 118 float vLast;
ryood 0:a08920b1cb6d 119 float tau0;
ryood 0:a08920b1cb6d 120 float tau1;
ryood 0:a08920b1cb6d 121 float attackTauRatio;
ryood 0:a08920b1cb6d 122 float releaseTauRatio;
ryood 0:a08920b1cb6d 123 };
ryood 0:a08920b1cb6d 124
ryood 0:a08920b1cb6d 125 //EnvelopeAR(int _attack, int _release, float _v0, float _v1, float _v2, float _attackTauRatio=0.36f, float _releaseTauRatio=0.36f) :
ryood 0:a08920b1cb6d 126 EnvelopeAR envelopeAmplitude(50, 200, 0.99f, 1.0f, 0.0f, 0.36f, 0.36f);
ryood 0:a08920b1cb6d 127
ryood 0:a08920b1cb6d 128 volatile int envelopeTicks;
ryood 0:a08920b1cb6d 129 volatile int envelopeLength;
ryood 0:a08920b1cb6d 130 volatile float amplitude;
ryood 0:a08920b1cb6d 131
ryood 0:a08920b1cb6d 132 int bpm;
ryood 0:a08920b1cb6d 133
ryood 0:a08920b1cb6d 134 void generateEnvelope()
ryood 0:a08920b1cb6d 135 {
ryood 0:a08920b1cb6d 136 // Amplitude Envelope
ryood 0:a08920b1cb6d 137 amplitude = envelopeAmplitude.getAmplitude(envelopeTicks);
ryood 0:a08920b1cb6d 138
ryood 0:a08920b1cb6d 139 #if UART_TRACE
ryood 0:a08920b1cb6d 140 printf("%8d\t%8d\t%f\r\n", envelopeLength, envelopeTicks, amplitude);
ryood 0:a08920b1cb6d 141 #endif
ryood 0:a08920b1cb6d 142
ryood 0:a08920b1cb6d 143 Dac1.write(amplitude);
ryood 0:a08920b1cb6d 144
ryood 0:a08920b1cb6d 145 envelopeTicks++;
ryood 0:a08920b1cb6d 146 if (envelopeTicks >= envelopeLength) {
ryood 0:a08920b1cb6d 147 envelopeTicks = 0;
ryood 0:a08920b1cb6d 148 }
ryood 0:a08920b1cb6d 149 }
ryood 0:a08920b1cb6d 150
ryood 0:a08920b1cb6d 151 void update()
ryood 0:a08920b1cb6d 152 {
ryood 0:a08920b1cb6d 153 generateEnvelope();
ryood 0:a08920b1cb6d 154 }
ryood 0:a08920b1cb6d 155
ryood 0:a08920b1cb6d 156 //------------------------------------------------------------------------------
ryood 0:a08920b1cb6d 157 // ここでパラメータを設定
ryood 0:a08920b1cb6d 158 //------------------------------------------------------------------------------
ryood 0:a08920b1cb6d 159 void setParams()
ryood 0:a08920b1cb6d 160 {
ryood 0:a08920b1cb6d 161 bpm = 120.0f;
ryood 0:a08920b1cb6d 162
ryood 0:a08920b1cb6d 163 envelopeLength = 60 * ENVELOPE_UPDATE_RATE / bpm;
ryood 0:a08920b1cb6d 164
ryood 0:a08920b1cb6d 165 envelopeAmplitude.setAttack(envelopeLength * 0.1f);
ryood 0:a08920b1cb6d 166 envelopeAmplitude.setRelease(envelopeLength * 0.6f);
ryood 0:a08920b1cb6d 167 envelopeAmplitude.setV0(0.99f);
ryood 0:a08920b1cb6d 168 envelopeAmplitude.setV1(1.0f);
ryood 0:a08920b1cb6d 169 envelopeAmplitude.setV2(0.0f);
ryood 0:a08920b1cb6d 170 envelopeAmplitude.setAttackTauRatio(0.36f);
ryood 0:a08920b1cb6d 171 envelopeAmplitude.setReleaseTauRatio(0.6f);
ryood 0:a08920b1cb6d 172 }
ryood 0:a08920b1cb6d 173
ryood 0:a08920b1cb6d 174 int main()
ryood 0:a08920b1cb6d 175 {
ryood 0:a08920b1cb6d 176 #if UART_TRACE
ryood 0:a08920b1cb6d 177 printf("%s %s\r\n", TITLE_STR1, TITLE_STR2);
ryood 0:a08920b1cb6d 178 #endif
ryood 0:a08920b1cb6d 179
ryood 0:a08920b1cb6d 180 setParams();
ryood 0:a08920b1cb6d 181 envelopeTicks = 0;
ryood 0:a08920b1cb6d 182
ryood 0:a08920b1cb6d 183 Ticker samplingTicker;
ryood 0:a08920b1cb6d 184 samplingTicker.attach(&update, SAMPLING_PERIOD);
ryood 0:a08920b1cb6d 185
ryood 0:a08920b1cb6d 186 for (;;) {}
ryood 0:a08920b1cb6d 187 }