Kick Machine Prototype

Dependencies:   mbed-rtos mbed

Committer:
ryood
Date:
Tue Jun 06 12:25:19 2017 +0000
Revision:
11:7e11404adca0
Parent:
10:79134dbb339d
first commit

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