Kick Machine Prototype

Dependencies:   mbed-rtos mbed

Committer:
ryood
Date:
Sun Jun 04 08:59:53 2017 +0000
Revision:
5:846772a77d33
Parent:
4:9f53a82fc1b6
Child:
6:897d6392b408
Impl. AnalogIn -> AmpEnvelpe

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ryood 3:f89b400cfe57 1 /*
ryood 3:f89b400cfe57 2 * KIK01
ryood 3:f89b400cfe57 3 * Kick Machine
ryood 3:f89b400cfe57 4 *
ryood 3:f89b400cfe57 5 * 2017.06.04 created.
ryood 3:f89b400cfe57 6 *
ryood 3:f89b400cfe57 7 */
ryood 3:f89b400cfe57 8
ryood 0:2dcec10e9199 9 #include "mbed.h"
ryood 0:2dcec10e9199 10 #include "rtos.h"
ryood 0:2dcec10e9199 11
ryood 0:2dcec10e9199 12 #define TITLE_STR1 ("KIK01 Kick Machine")
ryood 0:2dcec10e9199 13 #define TITLE_STR2 ("20170604")
ryood 0:2dcec10e9199 14
ryood 0:2dcec10e9199 15 #define PI_F (3.1415926f)
ryood 5:846772a77d33 16 #define SAMPLING_RATE (48000)
ryood 0:2dcec10e9199 17 #define SAMPLING_PERIOD (1.0f/SAMPLING_RATE)
ryood 0:2dcec10e9199 18
ryood 0:2dcec10e9199 19 #define FREQUENCY_ATTACK (5)
ryood 0:2dcec10e9199 20 #define FREQUENCY_RELEASE (300)
ryood 4:9f53a82fc1b6 21 //#define AMPLITUDE_ATTACK (50)
ryood 5:846772a77d33 22 //#define AMPLITUDE_RELEASE (200)
ryood 0:2dcec10e9199 23
ryood 3:f89b400cfe57 24 AnalogOut Dac1(PA_5);
ryood 3:f89b400cfe57 25
ryood 5:846772a77d33 26 AnalogIn Ain0(PA_0);
ryood 5:846772a77d33 27 AnalogIn Ain1(PA_1);
ryood 5:846772a77d33 28 AnalogIn Ain2(PA_4);
ryood 5:846772a77d33 29 AnalogIn Ain3(PB_0);
ryood 5:846772a77d33 30 AnalogIn Ain4(PC_1);
ryood 5:846772a77d33 31 AnalogIn Ain5(PC_0);
ryood 5:846772a77d33 32 AnalogIn Ain6(PC_2);
ryood 5:846772a77d33 33 AnalogIn Ain7(PC_3);
ryood 0:2dcec10e9199 34
ryood 0:2dcec10e9199 35 class EnvelopeAR {
ryood 0:2dcec10e9199 36 public:
ryood 0:2dcec10e9199 37 EnvelopeAR(int _attack, int _release, float _v0, float _v1, float _v2, float _attackTauRatio=0.36f, float _releaseTauRatio=0.36f) :
ryood 0:2dcec10e9199 38 amplitude(_v0),
ryood 0:2dcec10e9199 39 v0(_v0),
ryood 0:2dcec10e9199 40 v1(_v1),
ryood 0:2dcec10e9199 41 v2(_v2),
ryood 0:2dcec10e9199 42 vLast(_v0),
ryood 0:2dcec10e9199 43 attackTauRatio(_attackTauRatio),
ryood 0:2dcec10e9199 44 releaseTauRatio(_releaseTauRatio)
ryood 0:2dcec10e9199 45 {
ryood 0:2dcec10e9199 46 setAttack(_attack);
ryood 0:2dcec10e9199 47 setRelease(_release);
ryood 0:2dcec10e9199 48 }
ryood 0:2dcec10e9199 49
ryood 0:2dcec10e9199 50 ~EnvelopeAR() {}
ryood 0:2dcec10e9199 51
ryood 0:2dcec10e9199 52 void setAttack(int _attack) {
ryood 0:2dcec10e9199 53 attack = _attack;
ryood 0:2dcec10e9199 54 tau0 = attack * attackTauRatio;
ryood 0:2dcec10e9199 55 }
ryood 0:2dcec10e9199 56 int getAttack() { return attack; }
ryood 0:2dcec10e9199 57
ryood 0:2dcec10e9199 58 void setRelease(int _release) {
ryood 0:2dcec10e9199 59 release = _release;
ryood 0:2dcec10e9199 60 tau1 = release * releaseTauRatio;
ryood 0:2dcec10e9199 61 }
ryood 0:2dcec10e9199 62 int getRelease() { return release; }
ryood 0:2dcec10e9199 63
ryood 5:846772a77d33 64 void setAttackTauRatio(float _attackTauRatio) {
ryood 5:846772a77d33 65 attackTauRatio = _attackTauRatio;
ryood 5:846772a77d33 66 tau0 = attack * attackTauRatio;
ryood 5:846772a77d33 67 }
ryood 0:2dcec10e9199 68 float getAttackTauRatio() { return attackTauRatio; }
ryood 0:2dcec10e9199 69
ryood 5:846772a77d33 70 void setReleaseTauRatio(float _releaseTauRatio) {
ryood 5:846772a77d33 71 releaseTauRatio = _releaseTauRatio;
ryood 5:846772a77d33 72 tau1 = release * releaseTauRatio;
ryood 5:846772a77d33 73 }
ryood 0:2dcec10e9199 74 float getReleaseTauRatio() { return releaseTauRatio; }
ryood 5:846772a77d33 75
ryood 5:846772a77d33 76 float getTau0() { return tau0; }
ryood 5:846772a77d33 77 float getTau1() { return tau1; }
ryood 0:2dcec10e9199 78
ryood 0:2dcec10e9199 79 void setV0(float _v0) { v0 = _v0; }
ryood 0:2dcec10e9199 80 float getV0() { return v0; }
ryood 0:2dcec10e9199 81 void setV1(float _v1) { v1 = _v1; }
ryood 0:2dcec10e9199 82 float getV1() { return v1; }
ryood 0:2dcec10e9199 83 void setV2(float _v2) { v2 = _v2; }
ryood 0:2dcec10e9199 84 float getV2() { return v2; }
ryood 0:2dcec10e9199 85
ryood 0:2dcec10e9199 86 float getAmplitude() { return amplitude; }
ryood 0:2dcec10e9199 87 float getAmplitude(int tick) {
ryood 0:2dcec10e9199 88 if (tick < attack) {
ryood 0:2dcec10e9199 89 // attackの処理
ryood 0:2dcec10e9199 90 amplitude = v0 + (v1 - v0) * (1 - expf(-(float)tick / tau0));
ryood 0:2dcec10e9199 91 vLast = amplitude;
ryood 0:2dcec10e9199 92 }
ryood 0:2dcec10e9199 93 else {
ryood 0:2dcec10e9199 94 // releaseの処理
ryood 0:2dcec10e9199 95 amplitude = (vLast - v2) * (expf(-(float)(tick - attack) / tau1)) + v2;
ryood 0:2dcec10e9199 96 }
ryood 0:2dcec10e9199 97 return amplitude;
ryood 0:2dcec10e9199 98 }
ryood 0:2dcec10e9199 99
ryood 0:2dcec10e9199 100 private:
ryood 0:2dcec10e9199 101 int attack;
ryood 0:2dcec10e9199 102 int release;
ryood 0:2dcec10e9199 103 float amplitude;
ryood 0:2dcec10e9199 104 float v0;
ryood 0:2dcec10e9199 105 float v1;
ryood 0:2dcec10e9199 106 float v2;
ryood 0:2dcec10e9199 107 float vLast;
ryood 0:2dcec10e9199 108 float tau0;
ryood 0:2dcec10e9199 109 float tau1;
ryood 0:2dcec10e9199 110 float attackTauRatio;
ryood 0:2dcec10e9199 111 float releaseTauRatio;
ryood 0:2dcec10e9199 112 };
ryood 0:2dcec10e9199 113
ryood 5:846772a77d33 114 class EnvelopeParam {
ryood 5:846772a77d33 115 public:
ryood 5:846772a77d33 116 int attack;
ryood 5:846772a77d33 117 int release;
ryood 5:846772a77d33 118 float v0;
ryood 5:846772a77d33 119 float v1;
ryood 5:846772a77d33 120 float v2;
ryood 5:846772a77d33 121 float attackTauRatio;
ryood 5:846772a77d33 122 float releaseTauRatio;
ryood 5:846772a77d33 123 };
ryood 5:846772a77d33 124
ryood 0:2dcec10e9199 125 EnvelopeAR envelopeFrequency(
ryood 0:2dcec10e9199 126 FREQUENCY_ATTACK, FREQUENCY_RELEASE, 880.0f, 120.0f, 40.0f, 0.36f, 0.1f);
ryood 5:846772a77d33 127 EnvelopeAR envelopeAmplitude(50, 200, 0.99f, 1.0f, 0.0f);
ryood 5:846772a77d33 128
ryood 5:846772a77d33 129 volatile EnvelopeParam frequencyParam;
ryood 5:846772a77d33 130 volatile EnvelopeParam amplitudeParam;
ryood 0:2dcec10e9199 131
ryood 3:f89b400cfe57 132 volatile int ticks;
ryood 3:f89b400cfe57 133 volatile int envelopeTicks;
ryood 3:f89b400cfe57 134 volatile float frequency;
ryood 3:f89b400cfe57 135 volatile float phi;
ryood 3:f89b400cfe57 136 volatile float phiDelta;
ryood 3:f89b400cfe57 137 volatile float amplitude;
ryood 3:f89b400cfe57 138
ryood 5:846772a77d33 139 volatile float bpm;
ryood 5:846772a77d33 140 volatile int envelopeLength;
ryood 0:2dcec10e9199 141
ryood 0:2dcec10e9199 142 void generateWave()
ryood 0:2dcec10e9199 143 {
ryood 0:2dcec10e9199 144 phi += phiDelta;
ryood 0:2dcec10e9199 145 if (phi >= 1.0f) {
ryood 0:2dcec10e9199 146 phi -= 2.0f;
ryood 0:2dcec10e9199 147 }
ryood 0:2dcec10e9199 148 float level = sinf(PI_F * phi) * amplitude;
ryood 1:f9b967ae26e4 149
ryood 3:f89b400cfe57 150 Dac1.write((level * 0.7f + 1.0f) / 2.0f);
ryood 0:2dcec10e9199 151 }
ryood 0:2dcec10e9199 152
ryood 0:2dcec10e9199 153 void generateEnvelope()
ryood 0:2dcec10e9199 154 {
ryood 0:2dcec10e9199 155 // Frequency Envelope
ryood 0:2dcec10e9199 156 frequency = envelopeFrequency.getAmplitude(envelopeTicks);
ryood 0:2dcec10e9199 157 phiDelta = 2.0f * frequency / SAMPLING_RATE;
ryood 0:2dcec10e9199 158
ryood 0:2dcec10e9199 159 // Amplitude Envelope
ryood 0:2dcec10e9199 160 amplitude = envelopeAmplitude.getAmplitude(envelopeTicks);
ryood 0:2dcec10e9199 161
ryood 0:2dcec10e9199 162 envelopeTicks++;
ryood 3:f89b400cfe57 163 if (envelopeTicks == envelopeLength) {
ryood 0:2dcec10e9199 164 envelopeTicks = 0;
ryood 0:2dcec10e9199 165 }
ryood 0:2dcec10e9199 166 }
ryood 0:2dcec10e9199 167
ryood 2:8dff77a1ee4d 168 void update()
ryood 2:8dff77a1ee4d 169 {
ryood 3:f89b400cfe57 170 ticks++;
ryood 3:f89b400cfe57 171 if (ticks == SAMPLING_RATE / 1000) {
ryood 3:f89b400cfe57 172 ticks = 0;
ryood 5:846772a77d33 173
ryood 5:846772a77d33 174 // set envelope parameters
ryood 5:846772a77d33 175 envelopeLength = 60 * 1000 / bpm;
ryood 5:846772a77d33 176
ryood 5:846772a77d33 177 envelopeAmplitude.setAttack(amplitudeParam.attack);
ryood 5:846772a77d33 178 envelopeAmplitude.setRelease(amplitudeParam.release);
ryood 5:846772a77d33 179 envelopeAmplitude.setV0(amplitudeParam.v0);
ryood 5:846772a77d33 180 envelopeAmplitude.setV1(amplitudeParam.v1);
ryood 5:846772a77d33 181 envelopeAmplitude.setV2(amplitudeParam.v2);
ryood 5:846772a77d33 182 envelopeAmplitude.setAttackTauRatio(amplitudeParam.attackTauRatio);
ryood 5:846772a77d33 183 envelopeAmplitude.setReleaseTauRatio(amplitudeParam.releaseTauRatio);
ryood 5:846772a77d33 184
ryood 5:846772a77d33 185 envelopeFrequency.setV0(frequencyParam.v0);
ryood 5:846772a77d33 186
ryood 2:8dff77a1ee4d 187 generateEnvelope();
ryood 2:8dff77a1ee4d 188 }
ryood 2:8dff77a1ee4d 189 generateWave();
ryood 2:8dff77a1ee4d 190 }
ryood 2:8dff77a1ee4d 191
ryood 5:846772a77d33 192 void setParams()
ryood 5:846772a77d33 193 {
ryood 5:846772a77d33 194 bpm = Ain0.read() * 180.0f + 60.0f;
ryood 5:846772a77d33 195
ryood 5:846772a77d33 196 amplitudeParam.attack = Ain1.read() * envelopeLength;
ryood 5:846772a77d33 197 amplitudeParam.release = Ain2.read() * envelopeLength;
ryood 5:846772a77d33 198 amplitudeParam.v0 = Ain3.read();
ryood 5:846772a77d33 199 amplitudeParam.v1 = 1.0f;
ryood 5:846772a77d33 200 amplitudeParam.v2 = 0.0f;
ryood 5:846772a77d33 201 amplitudeParam.attackTauRatio = 0.36f;
ryood 5:846772a77d33 202 amplitudeParam.releaseTauRatio = 0.36f;
ryood 5:846772a77d33 203
ryood 5:846772a77d33 204 frequencyParam.v0 = Ain5.read() * 3000.0f + 50.0f;
ryood 5:846772a77d33 205 frequencyParam.v1 = frequencyParam.v0;
ryood 5:846772a77d33 206 }
ryood 5:846772a77d33 207
ryood 0:2dcec10e9199 208 int main()
ryood 0:2dcec10e9199 209 {
ryood 0:2dcec10e9199 210 printf("%s %s\r\n", TITLE_STR1, TITLE_STR2);
ryood 0:2dcec10e9199 211
ryood 0:2dcec10e9199 212 frequency = 1000.0f;
ryood 0:2dcec10e9199 213 phiDelta = 2.0f * frequency / SAMPLING_RATE;
ryood 0:2dcec10e9199 214 amplitude = 1.0f;
ryood 0:2dcec10e9199 215
ryood 3:f89b400cfe57 216 ticks = 0;
ryood 2:8dff77a1ee4d 217 envelopeTicks = 0;
ryood 1:f9b967ae26e4 218
ryood 5:846772a77d33 219 bpm = 120.0f;
ryood 5:846772a77d33 220 setParams();
ryood 5:846772a77d33 221
ryood 2:8dff77a1ee4d 222 Ticker samplingTicker;
ryood 2:8dff77a1ee4d 223 samplingTicker.attach(&update, SAMPLING_PERIOD);
ryood 2:8dff77a1ee4d 224
ryood 3:f89b400cfe57 225 for (;;) {
ryood 5:846772a77d33 226 setParams();
ryood 5:846772a77d33 227 printf("%.1f\t%d\t%d\t%.1f\r\n",
ryood 5:846772a77d33 228 bpm,
ryood 5:846772a77d33 229 envelopeLength,
ryood 5:846772a77d33 230 amplitudeParam.attack,
ryood 5:846772a77d33 231 frequencyParam.v0
ryood 5:846772a77d33 232 );
ryood 4:9f53a82fc1b6 233 Thread::wait(500);
ryood 3:f89b400cfe57 234 }
ryood 0:2dcec10e9199 235 }