Simple synthesizer for STM32F401RE/STMstation.
Dependencies: FastPWM mbed-dsp
This is a basic synthesizer to play music on the STM32F401RE Nucleo/STMstation development board:
Please see the API documentation for further details.
Here's a demo of the synthesizer at work in a music composing program on the STMstation. This one is "Miku" by Anamanaguchi.
STMstation_synth.cpp@1:db0c24aebb8a, 2017-07-03 (annotated)
- Committer:
- kkado
- Date:
- Mon Jul 03 08:35:31 2017 +0000
- Revision:
- 1:db0c24aebb8a
- Parent:
- 0:c5ca205c0a80
Corrected documentation placement.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kkado | 0:c5ca205c0a80 | 1 | #include "STMstation_synth.h" |
kkado | 0:c5ca205c0a80 | 2 | #include "mbed.h" |
kkado | 0:c5ca205c0a80 | 3 | #include "arm_math.h" |
kkado | 0:c5ca205c0a80 | 4 | #include "FastPWM.h" |
kkado | 0:c5ca205c0a80 | 5 | |
kkado | 0:c5ca205c0a80 | 6 | const float freqs[] = {0,46.2493,48.9995,51.913,55,58.2705,61.7354,65.4064,69.2957,73.4162,77.7817,82.4069,87.3071,92.4986,97.9989,103.826,110,116.541,123.471,130.813,138.591,146.832,155.563,164.814,174.614,184.997,195.998,207.652,220,233.082,246.942,261.626,277.183,293.665,311.127,329.628,349.228,369.994,391.995,415.305,440,466.164,493.883,523.251,554.365,587.33,622.254,659.255,698.456,739.989,783.991,830.609,880,932.328,987.767,1046.5,1108.73,1174.66,1244.51,1318.51,1396.91,1479.98,1567.98,1661.22,1760,1864.66,1975.53,2093,2217.46,2349.32,2489.02,2637.02,2793.83,2959.96,3135.96,3322.44,3520,3729.31,3951.07,4186.01}; |
kkado | 0:c5ca205c0a80 | 7 | const uint8_t freqLength = sizeof(freqs)/sizeof(freqs[0]); |
kkado | 0:c5ca205c0a80 | 8 | const float pi = 3.14159265359; |
kkado | 0:c5ca205c0a80 | 9 | |
kkado | 1:db0c24aebb8a | 10 | //Sampling rate, uncomment one line only! |
kkado | 1:db0c24aebb8a | 11 | //const uint16_t FSAMP = 44100; const float period = 0.000023; |
kkado | 1:db0c24aebb8a | 12 | //const uint16_t FSAMP = 22050; const float period = 0.000045; |
kkado | 1:db0c24aebb8a | 13 | const uint16_t FSAMP = 11025; const float period = 0.000091; |
kkado | 1:db0c24aebb8a | 14 | |
kkado | 0:c5ca205c0a80 | 15 | //Constructor |
kkado | 1:db0c24aebb8a | 16 | STMstation_synth::STMstation_synth():tone(AUDIO_PIN,1) |
kkado | 0:c5ca205c0a80 | 17 | { |
kkado | 1:db0c24aebb8a | 18 | begin(); |
kkado | 0:c5ca205c0a80 | 19 | } |
kkado | 0:c5ca205c0a80 | 20 | |
kkado | 1:db0c24aebb8a | 21 | //Constructor |
kkado | 1:db0c24aebb8a | 22 | STMstation_synth::STMstation_synth(PinName audio_pin):tone(audio_pin,1) |
kkado | 1:db0c24aebb8a | 23 | { |
kkado | 1:db0c24aebb8a | 24 | begin(); |
kkado | 1:db0c24aebb8a | 25 | } |
kkado | 1:db0c24aebb8a | 26 | |
kkado | 1:db0c24aebb8a | 27 | //Set up PWM and timer interrupt |
kkado | 1:db0c24aebb8a | 28 | void STMstation_synth::begin(){ |
kkado | 1:db0c24aebb8a | 29 | tone.pulsewidth_ticks(128); |
kkado | 1:db0c24aebb8a | 30 | tone.period_ticks(256); |
kkado | 1:db0c24aebb8a | 31 | sample.attach(this,&STMstation_synth::note,period); |
kkado | 1:db0c24aebb8a | 32 | } |
kkado | 0:c5ca205c0a80 | 33 | |
kkado | 0:c5ca205c0a80 | 34 | //Calculate the coefficients |
kkado | 0:c5ca205c0a80 | 35 | void STMstation_synth::calc_coefs(int i){ |
kkado | 0:c5ca205c0a80 | 36 | Master.timbre[i] = Master.notes[i][Master.index[i]]/freqLength; |
kkado | 0:c5ca205c0a80 | 37 | |
kkado | 0:c5ca205c0a80 | 38 | uint8_t _freq_index = Master.notes[i][Master.index[i]] % freqLength; |
kkado | 0:c5ca205c0a80 | 39 | float _freq = freqs[_freq_index]; |
kkado | 0:c5ca205c0a80 | 40 | uint32_t _duration = floor(0.5f + FSAMP*60.0f/Master.bpm[i]*(Master.durations[i][Master.index[i]]+1.0f)/16.0f); |
kkado | 0:c5ca205c0a80 | 41 | uint8_t _attack = Master.AR[i][Master.index[i]] >> 4; |
kkado | 0:c5ca205c0a80 | 42 | uint8_t _release = Master.AR[i][Master.index[i]] & 0b00001111; |
kkado | 0:c5ca205c0a80 | 43 | |
kkado | 0:c5ca205c0a80 | 44 | Master.freqIndex[i] = _freq_index; |
kkado | 0:c5ca205c0a80 | 45 | Master.sineCoef[i] = 2*pi/FSAMP*_freq; |
kkado | 0:c5ca205c0a80 | 46 | if(_freq == 0){Master.halfPeriod[i] = 0;} |
kkado | 0:c5ca205c0a80 | 47 | else{Master.halfPeriod[i] = FSAMP/(2*_freq);} |
kkado | 0:c5ca205c0a80 | 48 | Master.triSlope[i] = 2/Master.halfPeriod[i]; |
kkado | 0:c5ca205c0a80 | 49 | Master.envAtkEnd[i] = _attack/16.0f*_duration; |
kkado | 0:c5ca205c0a80 | 50 | Master.envRelStart[i] = (1-_release/16.0f)*_duration; |
kkado | 0:c5ca205c0a80 | 51 | if(_attack == 0){Master.atkSlope[i] = 0;} |
kkado | 0:c5ca205c0a80 | 52 | else{Master.atkSlope[i] = 16.0f/(_attack*_duration);} |
kkado | 0:c5ca205c0a80 | 53 | if(_release == 0){Master.relSlope[i] = 0;} |
kkado | 0:c5ca205c0a80 | 54 | else{Master.relSlope[i] = 16.0f/(_release*_duration);} |
kkado | 0:c5ca205c0a80 | 55 | Master.relOffset[i] = 16.0f/_release; |
kkado | 0:c5ca205c0a80 | 56 | Master.volCoef[i] = Master.vol[i][Master.index[i]]/Master.vSum; |
kkado | 0:c5ca205c0a80 | 57 | } |
kkado | 0:c5ca205c0a80 | 58 | |
kkado | 0:c5ca205c0a80 | 59 | //Calculate vSum |
kkado | 1:db0c24aebb8a | 60 | void STMstation_synth::calc_vSum(){ |
kkado | 0:c5ca205c0a80 | 61 | uint8_t active = 0; //Number of active channels |
kkado | 0:c5ca205c0a80 | 62 | uint16_t accum = 0; //Sum of volume channel values |
kkado | 0:c5ca205c0a80 | 63 | bool over = 0; //Is any value over 127? |
kkado | 0:c5ca205c0a80 | 64 | for(int i=0; i<CHANNELS; i++){ |
kkado | 0:c5ca205c0a80 | 65 | if(Master.notes[i] != NULL){ |
kkado | 0:c5ca205c0a80 | 66 | active++; |
kkado | 0:c5ca205c0a80 | 67 | accum += Master.vol[i][Master.index[i]]; |
kkado | 0:c5ca205c0a80 | 68 | if(Master.vol[i][Master.index[i]] > 127){over = 1;} |
kkado | 0:c5ca205c0a80 | 69 | } |
kkado | 0:c5ca205c0a80 | 70 | } |
kkado | 0:c5ca205c0a80 | 71 | if(accum == 0) {Master.vSum = 1;} |
kkado | 0:c5ca205c0a80 | 72 | else if(over == 0) {Master.vSum = active*127;} |
kkado | 0:c5ca205c0a80 | 73 | else {Master.vSum = accum;} |
kkado | 0:c5ca205c0a80 | 74 | } |
kkado | 0:c5ca205c0a80 | 75 | |
kkado | 0:c5ca205c0a80 | 76 | // Calculate the envelope |
kkado | 0:c5ca205c0a80 | 77 | void STMstation_synth::calc_env(){ |
kkado | 0:c5ca205c0a80 | 78 | for(int i=0; i<CHANNELS; i++){ |
kkado | 0:c5ca205c0a80 | 79 | if(Master.notes[i] != NULL){ |
kkado | 0:c5ca205c0a80 | 80 | if(Master.counter[i] < Master.envAtkEnd[i]){ |
kkado | 0:c5ca205c0a80 | 81 | if(Master.atkSlope == 0){Master.env[i] = 1;} |
kkado | 0:c5ca205c0a80 | 82 | else{Master.env[i] = Master.atkSlope[i]*Master.counter[i];} |
kkado | 0:c5ca205c0a80 | 83 | } |
kkado | 0:c5ca205c0a80 | 84 | else if(Master.counter[i] > Master.envRelStart[i]){ |
kkado | 0:c5ca205c0a80 | 85 | if(Master.relSlope == 0){Master.env[i] = 1;} |
kkado | 0:c5ca205c0a80 | 86 | else{Master.env[i] = Master.relOffset[i] - Master.relSlope[i]*Master.counter[i];} |
kkado | 0:c5ca205c0a80 | 87 | } |
kkado | 0:c5ca205c0a80 | 88 | else{ |
kkado | 0:c5ca205c0a80 | 89 | Master.env[i] = 1; |
kkado | 0:c5ca205c0a80 | 90 | } |
kkado | 0:c5ca205c0a80 | 91 | } |
kkado | 0:c5ca205c0a80 | 92 | } |
kkado | 0:c5ca205c0a80 | 93 | } |
kkado | 0:c5ca205c0a80 | 94 | |
kkado | 0:c5ca205c0a80 | 95 | //Square wave switching function |
kkado | 0:c5ca205c0a80 | 96 | int8_t STMstation_synth::square(float _halfperiod, uint16_t _counter){ |
kkado | 0:c5ca205c0a80 | 97 | if(_halfperiod == 0){ |
kkado | 0:c5ca205c0a80 | 98 | return 0;; |
kkado | 0:c5ca205c0a80 | 99 | } |
kkado | 0:c5ca205c0a80 | 100 | |
kkado | 0:c5ca205c0a80 | 101 | uint32_t _div = _counter/_halfperiod; |
kkado | 0:c5ca205c0a80 | 102 | uint32_t _div2 = _div % 2; |
kkado | 0:c5ca205c0a80 | 103 | if(_div2 == 0){ |
kkado | 0:c5ca205c0a80 | 104 | return -1; |
kkado | 0:c5ca205c0a80 | 105 | } |
kkado | 0:c5ca205c0a80 | 106 | else{ |
kkado | 0:c5ca205c0a80 | 107 | return 1; |
kkado | 0:c5ca205c0a80 | 108 | } |
kkado | 0:c5ca205c0a80 | 109 | } |
kkado | 0:c5ca205c0a80 | 110 | |
kkado | 0:c5ca205c0a80 | 111 | //Triangle wave function |
kkado | 0:c5ca205c0a80 | 112 | void STMstation_synth::calc_triangle(uint8_t _channel, float _halfperiod, float _trislope, uint32_t _counter){ |
kkado | 0:c5ca205c0a80 | 113 | if(_halfperiod == 0){ |
kkado | 0:c5ca205c0a80 | 114 | Master.triVal[_channel] = 0; |
kkado | 0:c5ca205c0a80 | 115 | return; |
kkado | 0:c5ca205c0a80 | 116 | } |
kkado | 0:c5ca205c0a80 | 117 | |
kkado | 0:c5ca205c0a80 | 118 | int8_t _sign = 2*(uint32_t(_counter/_halfperiod) % 2) - 1; |
kkado | 0:c5ca205c0a80 | 119 | Master.triVal[_channel] += _sign*_trislope; |
kkado | 0:c5ca205c0a80 | 120 | if(_counter == 0){ |
kkado | 0:c5ca205c0a80 | 121 | Master.triVal[_channel] = 1; |
kkado | 0:c5ca205c0a80 | 122 | } |
kkado | 0:c5ca205c0a80 | 123 | if(Master.triVal[_channel] < -1){ |
kkado | 0:c5ca205c0a80 | 124 | Master.triVal[_channel] = -1; |
kkado | 0:c5ca205c0a80 | 125 | } |
kkado | 0:c5ca205c0a80 | 126 | else if(Master.triVal[_channel] > 1){ |
kkado | 0:c5ca205c0a80 | 127 | Master.triVal[_channel] = 1; |
kkado | 0:c5ca205c0a80 | 128 | } |
kkado | 0:c5ca205c0a80 | 129 | } |
kkado | 0:c5ca205c0a80 | 130 | |
kkado | 0:c5ca205c0a80 | 131 | //Calculate noise |
kkado | 0:c5ca205c0a80 | 132 | void STMstation_synth::calc_noise(uint8_t _channel, uint8_t _freq, uint32_t _counter){ |
kkado | 0:c5ca205c0a80 | 133 | if(_freq == 0){ |
kkado | 0:c5ca205c0a80 | 134 | Master.noiseVal[_channel] = 0; |
kkado | 0:c5ca205c0a80 | 135 | return; |
kkado | 0:c5ca205c0a80 | 136 | } |
kkado | 0:c5ca205c0a80 | 137 | |
kkado | 0:c5ca205c0a80 | 138 | uint32_t _noisePeriod = (16-_freq); |
kkado | 0:c5ca205c0a80 | 139 | if(_counter % _noisePeriod == 0){ |
kkado | 0:c5ca205c0a80 | 140 | Master.noiseVal[_channel] = 1-(rand() % 257)/128.0f; |
kkado | 0:c5ca205c0a80 | 141 | } |
kkado | 0:c5ca205c0a80 | 142 | } |
kkado | 0:c5ca205c0a80 | 143 | |
kkado | 0:c5ca205c0a80 | 144 | //Calculate values |
kkado | 1:db0c24aebb8a | 145 | void STMstation_synth::calc_val(){ |
kkado | 0:c5ca205c0a80 | 146 | Master.val = 128; |
kkado | 0:c5ca205c0a80 | 147 | for(int i=0; i<CHANNELS; i++){ |
kkado | 0:c5ca205c0a80 | 148 | if(Master.notes[i] != NULL){ |
kkado | 0:c5ca205c0a80 | 149 | if(Master.timbre[i] == 0){ |
kkado | 0:c5ca205c0a80 | 150 | Master.val += 127*arm_sin_f32(Master.sineCoef[i]*Master.counter[i])*Master.env[i]*Master.volCoef[i]; |
kkado | 0:c5ca205c0a80 | 151 | } |
kkado | 0:c5ca205c0a80 | 152 | else if(Master.timbre[i] == 1){ |
kkado | 0:c5ca205c0a80 | 153 | Master.val += 127*square(Master.halfPeriod[i], Master.counter[i])*Master.env[i]*Master.volCoef[i]; |
kkado | 0:c5ca205c0a80 | 154 | } |
kkado | 0:c5ca205c0a80 | 155 | else if(Master.timbre[i] == 2){ |
kkado | 0:c5ca205c0a80 | 156 | calc_triangle(i,Master.halfPeriod[i], Master.triSlope[i], Master.counter[i]); |
kkado | 0:c5ca205c0a80 | 157 | Master.val += 127*Master.triVal[i]*Master.env[i]*Master.volCoef[i]; |
kkado | 0:c5ca205c0a80 | 158 | } |
kkado | 0:c5ca205c0a80 | 159 | else if(Master.timbre[i] == 3){ |
kkado | 0:c5ca205c0a80 | 160 | calc_noise(i,Master.freqIndex[i],Master.counter[i]); |
kkado | 0:c5ca205c0a80 | 161 | Master.val += 127*Master.noiseVal[i]*Master.env[i]*Master.volCoef[i]; |
kkado | 0:c5ca205c0a80 | 162 | } |
kkado | 0:c5ca205c0a80 | 163 | } |
kkado | 0:c5ca205c0a80 | 164 | } |
kkado | 0:c5ca205c0a80 | 165 | } |
kkado | 0:c5ca205c0a80 | 166 | |
kkado | 0:c5ca205c0a80 | 167 | //Remove channel |
kkado | 0:c5ca205c0a80 | 168 | void STMstation_synth::clear_channel(uint8_t _channel){ |
kkado | 0:c5ca205c0a80 | 169 | Master.notes[_channel] = NULL; |
kkado | 0:c5ca205c0a80 | 170 | Master.durations[_channel] = NULL; |
kkado | 0:c5ca205c0a80 | 171 | Master.AR[_channel] = NULL; |
kkado | 0:c5ca205c0a80 | 172 | Master.vol[_channel] = NULL; |
kkado | 0:c5ca205c0a80 | 173 | Master.max[_channel] = NULL; |
kkado | 0:c5ca205c0a80 | 174 | Master.repeat[_channel] = NULL; |
kkado | 0:c5ca205c0a80 | 175 | Master.counter[_channel] = NULL; |
kkado | 0:c5ca205c0a80 | 176 | Master.index[_channel] = NULL; |
kkado | 0:c5ca205c0a80 | 177 | *(Master.endptr[_channel]) = 1; |
kkado | 0:c5ca205c0a80 | 178 | } |
kkado | 0:c5ca205c0a80 | 179 | |
kkado | 0:c5ca205c0a80 | 180 | //Stop track |
kkado | 0:c5ca205c0a80 | 181 | void STMstation_synth::stop_track(melody &newMelody){ |
kkado | 0:c5ca205c0a80 | 182 | for(uint16_t i=0; i<CHANNELS; i++){ |
kkado | 0:c5ca205c0a80 | 183 | if(newMelody.notes[i] != NULL){ |
kkado | 0:c5ca205c0a80 | 184 | clear_channel(i); |
kkado | 0:c5ca205c0a80 | 185 | } |
kkado | 0:c5ca205c0a80 | 186 | } |
kkado | 0:c5ca205c0a80 | 187 | } |
kkado | 0:c5ca205c0a80 | 188 | |
kkado | 0:c5ca205c0a80 | 189 | //Check if track is playing, returns 0 if all channels ended, 1 otherwise |
kkado | 0:c5ca205c0a80 | 190 | bool STMstation_synth::check_track(melody &newMelody){ |
kkado | 0:c5ca205c0a80 | 191 | for(uint16_t i=0; i<CHANNELS; i++){ |
kkado | 0:c5ca205c0a80 | 192 | if(newMelody.ended[i] == 0){ |
kkado | 0:c5ca205c0a80 | 193 | return 1; |
kkado | 0:c5ca205c0a80 | 194 | } |
kkado | 0:c5ca205c0a80 | 195 | } |
kkado | 0:c5ca205c0a80 | 196 | return 0; |
kkado | 0:c5ca205c0a80 | 197 | } |
kkado | 0:c5ca205c0a80 | 198 | |
kkado | 0:c5ca205c0a80 | 199 | //Check if notes are finished playing |
kkado | 0:c5ca205c0a80 | 200 | void STMstation_synth::check_end(){ |
kkado | 0:c5ca205c0a80 | 201 | uint32_t _duration; |
kkado | 0:c5ca205c0a80 | 202 | for(int i=0; i<CHANNELS; i++){ |
kkado | 0:c5ca205c0a80 | 203 | _duration = floor(0.5f + FSAMP*60.0f/Master.bpm[i]*(Master.durations[i][Master.index[i]]+1.0f)/16.0f); |
kkado | 0:c5ca205c0a80 | 204 | if(Master.counter[i] >= _duration){ |
kkado | 0:c5ca205c0a80 | 205 | if(Master.index[i] < Master.max[i]){ |
kkado | 0:c5ca205c0a80 | 206 | Master.index[i]++; |
kkado | 0:c5ca205c0a80 | 207 | } |
kkado | 0:c5ca205c0a80 | 208 | else{ |
kkado | 0:c5ca205c0a80 | 209 | if(Master.repeat[i] == 1){ |
kkado | 0:c5ca205c0a80 | 210 | Master.index[i] = 0; |
kkado | 0:c5ca205c0a80 | 211 | *(Master.endptr[i]) = 1; |
kkado | 0:c5ca205c0a80 | 212 | } |
kkado | 0:c5ca205c0a80 | 213 | else{ |
kkado | 0:c5ca205c0a80 | 214 | clear_channel(i); |
kkado | 0:c5ca205c0a80 | 215 | *(Master.endptr[i]) = 1; |
kkado | 0:c5ca205c0a80 | 216 | } |
kkado | 0:c5ca205c0a80 | 217 | } |
kkado | 0:c5ca205c0a80 | 218 | Master.counter[i] = 0; |
kkado | 0:c5ca205c0a80 | 219 | } |
kkado | 0:c5ca205c0a80 | 220 | else{ |
kkado | 0:c5ca205c0a80 | 221 | Master.counter[i]++; |
kkado | 0:c5ca205c0a80 | 222 | } |
kkado | 0:c5ca205c0a80 | 223 | } |
kkado | 0:c5ca205c0a80 | 224 | } |
kkado | 0:c5ca205c0a80 | 225 | |
kkado | 0:c5ca205c0a80 | 226 | //Check if a new note is starting and if we need to recalculate coefficients |
kkado | 0:c5ca205c0a80 | 227 | void STMstation_synth::check_start(){ |
kkado | 0:c5ca205c0a80 | 228 | for(int i=0; i<CHANNELS; i++){ |
kkado | 0:c5ca205c0a80 | 229 | if(Master.counter[i] == 0){ |
kkado | 1:db0c24aebb8a | 230 | calc_vSum(); |
kkado | 0:c5ca205c0a80 | 231 | calc_coefs(i); |
kkado | 0:c5ca205c0a80 | 232 | } |
kkado | 0:c5ca205c0a80 | 233 | } |
kkado | 0:c5ca205c0a80 | 234 | } |
kkado | 0:c5ca205c0a80 | 235 | |
kkado | 0:c5ca205c0a80 | 236 | //Play dat funky music |
kkado | 1:db0c24aebb8a | 237 | void STMstation_synth::note(){ |
kkado | 0:c5ca205c0a80 | 238 | check_start(); |
kkado | 0:c5ca205c0a80 | 239 | calc_env(); |
kkado | 1:db0c24aebb8a | 240 | calc_val(); |
kkado | 0:c5ca205c0a80 | 241 | tone.pulsewidth_ticks(Master.val); |
kkado | 0:c5ca205c0a80 | 242 | check_end(); |
kkado | 0:c5ca205c0a80 | 243 | } |
kkado | 0:c5ca205c0a80 | 244 | |
kkado | 0:c5ca205c0a80 | 245 | //Start playing a tune |
kkado | 0:c5ca205c0a80 | 246 | void STMstation_synth::play(melody &newMelody, uint8_t refChannel, uint16_t newIndex){ |
kkado | 0:c5ca205c0a80 | 247 | uint32_t pos = 0; |
kkado | 0:c5ca205c0a80 | 248 | uint32_t rem; |
kkado | 0:c5ca205c0a80 | 249 | uint16_t chanIndex; |
kkado | 0:c5ca205c0a80 | 250 | |
kkado | 0:c5ca205c0a80 | 251 | //pc.printf("Playing track...\n"); |
kkado | 0:c5ca205c0a80 | 252 | //pc.printf("refChannel = %d, newIndex = %d\n", refChannel, newIndex); |
kkado | 0:c5ca205c0a80 | 253 | |
kkado | 0:c5ca205c0a80 | 254 | //Calculate how far into the track we're at, in terms of samples |
kkado | 0:c5ca205c0a80 | 255 | for(uint16_t i=0; i<newIndex; i++){ |
kkado | 0:c5ca205c0a80 | 256 | pos += floor(0.5f + FSAMP*60.0f/newMelody.bpm*(newMelody.durations[refChannel][i]+1.0f)/16.0f); |
kkado | 0:c5ca205c0a80 | 257 | } |
kkado | 0:c5ca205c0a80 | 258 | |
kkado | 0:c5ca205c0a80 | 259 | //pc.printf("pos = %d\n",pos); |
kkado | 0:c5ca205c0a80 | 260 | |
kkado | 0:c5ca205c0a80 | 261 | for(int i=0; i<CHANNELS; i++){ |
kkado | 0:c5ca205c0a80 | 262 | if(newMelody.notes[i] != NULL){ |
kkado | 0:c5ca205c0a80 | 263 | chanIndex = 0; |
kkado | 0:c5ca205c0a80 | 264 | rem = pos; |
kkado | 0:c5ca205c0a80 | 265 | for(uint16_t j=0; j<=newMelody.max[i]; j++){ |
kkado | 0:c5ca205c0a80 | 266 | if(rem < floor(0.5f + FSAMP*60.0f/newMelody.bpm*(newMelody.durations[i][j]+1.0f)/16.0f)){ |
kkado | 0:c5ca205c0a80 | 267 | *(Master.endptr[i]) = 1; //Important! Overwrite the old .ended back to zero! |
kkado | 0:c5ca205c0a80 | 268 | Master.notes[i] = newMelody.notes[i]; |
kkado | 0:c5ca205c0a80 | 269 | Master.durations[i] = newMelody.durations[i]; |
kkado | 0:c5ca205c0a80 | 270 | Master.AR[i] = newMelody.AR[i]; |
kkado | 0:c5ca205c0a80 | 271 | Master.vol[i] = newMelody.vol[i]; |
kkado | 0:c5ca205c0a80 | 272 | Master.max[i] = newMelody.max[i]; |
kkado | 0:c5ca205c0a80 | 273 | Master.repeat[i] = newMelody.repeat[i]; |
kkado | 0:c5ca205c0a80 | 274 | Master.endptr[i] = &newMelody.ended[i]; //Now we set the .ended pointer to the new track's |
kkado | 0:c5ca205c0a80 | 275 | *(Master.endptr[i]) = 0; //Now we set the new track's .ended back to zero. |
kkado | 0:c5ca205c0a80 | 276 | Master.counter[i] = rem; |
kkado | 0:c5ca205c0a80 | 277 | Master.index[i] = chanIndex; |
kkado | 0:c5ca205c0a80 | 278 | Master.bpm[i] = newMelody.bpm; |
kkado | 0:c5ca205c0a80 | 279 | //pc.printf("Channel %d: chanIndex = %d, rem = %d\n",i,chanIndex,rem); |
kkado | 0:c5ca205c0a80 | 280 | break; |
kkado | 0:c5ca205c0a80 | 281 | } |
kkado | 0:c5ca205c0a80 | 282 | else{ |
kkado | 0:c5ca205c0a80 | 283 | rem -= floor(0.5f + FSAMP*60.0f/newMelody.bpm*(newMelody.durations[i][j]+1.0f)/16.0f); |
kkado | 0:c5ca205c0a80 | 284 | chanIndex++; |
kkado | 0:c5ca205c0a80 | 285 | } |
kkado | 0:c5ca205c0a80 | 286 | } |
kkado | 0:c5ca205c0a80 | 287 | } |
kkado | 0:c5ca205c0a80 | 288 | } |
kkado | 1:db0c24aebb8a | 289 | calc_vSum(); |
kkado | 0:c5ca205c0a80 | 290 | for(uint16_t i=0; i<CHANNELS; i++){ |
kkado | 0:c5ca205c0a80 | 291 | if(Master.notes[i]!=NULL){ |
kkado | 0:c5ca205c0a80 | 292 | calc_coefs(i); |
kkado | 0:c5ca205c0a80 | 293 | } |
kkado | 0:c5ca205c0a80 | 294 | } |
kkado | 0:c5ca205c0a80 | 295 | } |