Auduino port

Dependencies:   mbed

Committer:
kshoji
Date:
Wed Sep 15 00:20:19 2010 +0000
Revision:
1:a553c5d93bb8
Parent:
0:831ef5c249ef

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kshoji 0:831ef5c249ef 1 #include <math.h>
kshoji 0:831ef5c249ef 2 #include "mbed.h"
kshoji 0:831ef5c249ef 3
kshoji 1:a553c5d93bb8 4 #define FEATURE_ORIGINAL_AUDUINO
kshoji 1:a553c5d93bb8 5
kshoji 0:831ef5c249ef 6 // Auduino for mbed
kshoji 0:831ef5c249ef 7 // Ported and arranged by Kaoru Shoji
kshoji 0:831ef5c249ef 8
kshoji 0:831ef5c249ef 9 // Original source code:
kshoji 0:831ef5c249ef 10 // Auduino, the Lo-Fi granular synthesiser
kshoji 0:831ef5c249ef 11 //
kshoji 0:831ef5c249ef 12 // by Peter Knight, Tinker.it http://tinker.it
kshoji 0:831ef5c249ef 13 //
kshoji 0:831ef5c249ef 14 // Help: http://code.google.com/p/tinkerit/wiki/Auduino
kshoji 0:831ef5c249ef 15 // More help: http://groups.google.com/group/auduino
kshoji 0:831ef5c249ef 16 //
kshoji 0:831ef5c249ef 17 // Changelog:
kshoji 0:831ef5c249ef 18 // 19 Nov 2008: Added support for ATmega8 boards
kshoji 0:831ef5c249ef 19 // 21 Mar 2009: Added support for ATmega328 boards
kshoji 0:831ef5c249ef 20 // 7 Apr 2009: Fixed interrupt vector for ATmega328 boards
kshoji 0:831ef5c249ef 21 // 8 Apr 2009: Added support for ATmega1280 boards (Arduino Mega)
kshoji 0:831ef5c249ef 22
kshoji 0:831ef5c249ef 23 // Analog in p16: Grain 1 pitch
kshoji 0:831ef5c249ef 24 // Analog in p17: Grain 1 decay
kshoji 0:831ef5c249ef 25 // Analog in p19: Grain 2 pitch
kshoji 0:831ef5c249ef 26 // Analog in p20: Grain 2 decay
kshoji 0:831ef5c249ef 27 // Analog in p15: Grain repetition frequency
kshoji 0:831ef5c249ef 28 // Analog out p18: Audio out
kshoji 0:831ef5c249ef 29
kshoji 0:831ef5c249ef 30 Ticker interrupt;
kshoji 0:831ef5c249ef 31 AnalogIn SYNC_CONTROL(p15);
kshoji 0:831ef5c249ef 32 AnalogIn GRAIN_FREQ_CONTROL(p16);
kshoji 0:831ef5c249ef 33 AnalogIn GRAIN_DECAY_CONTROL(p17);
kshoji 0:831ef5c249ef 34 AnalogIn GRAIN2_FREQ_CONTROL(p19);
kshoji 0:831ef5c249ef 35 AnalogIn GRAIN2_DECAY_CONTROL(p20);
kshoji 0:831ef5c249ef 36 AnalogOut OUTPUT(p18);
kshoji 0:831ef5c249ef 37 DigitalOut LED_PIN(LED1);
kshoji 0:831ef5c249ef 38
kshoji 0:831ef5c249ef 39 float syncPhaseAcc;
kshoji 0:831ef5c249ef 40 float syncPhaseInc;
kshoji 0:831ef5c249ef 41
kshoji 0:831ef5c249ef 42 float grainPhaseAcc;
kshoji 0:831ef5c249ef 43 float grainPhaseInc;
kshoji 0:831ef5c249ef 44 float grainAmp;
kshoji 0:831ef5c249ef 45 float grainDecay;
kshoji 0:831ef5c249ef 46
kshoji 0:831ef5c249ef 47 float grain2PhaseAcc;
kshoji 0:831ef5c249ef 48 float grain2PhaseInc;
kshoji 0:831ef5c249ef 49 float grain2Amp;
kshoji 0:831ef5c249ef 50 float grain2Decay;
kshoji 0:831ef5c249ef 51
kshoji 0:831ef5c249ef 52 // Smooth logarithmic mapping
kshoji 0:831ef5c249ef 53 //
kshoji 0:831ef5c249ef 54 float mapPhaseInc(double input) {
kshoji 0:831ef5c249ef 55 return pow(65536.0, 1.0 - input);
kshoji 0:831ef5c249ef 56 }
kshoji 0:831ef5c249ef 57
kshoji 0:831ef5c249ef 58 // Stepped chromatic mapping
kshoji 0:831ef5c249ef 59 //
kshoji 0:831ef5c249ef 60 uint16_t midiTable[] = {
kshoji 0:831ef5c249ef 61 17,18,19,20,22,23,24,26,27,29,31,32,34,36,38,41,43,46,48,51,54,58,61,65,69,73,
kshoji 0:831ef5c249ef 62 77,82,86,92,97,103,109,115,122,129,137,145,154,163,173,183,194,206,218,231,
kshoji 0:831ef5c249ef 63 244,259,274,291,308,326,346,366,388,411,435,461,489,518,549,581,616,652,691,
kshoji 0:831ef5c249ef 64 732,776,822,871,923,978,1036,1097,1163,1232,1305,1383,1465,1552,1644,1742,
kshoji 0:831ef5c249ef 65 1845,1955,2071,2195,2325,2463,2610,2765,2930,3104,3288,3484,3691,3910,4143,
kshoji 0:831ef5c249ef 66 4389,4650,4927,5220,5530,5859,6207,6577,6968,7382,7821,8286,8779,9301,9854,
kshoji 0:831ef5c249ef 67 10440,11060,11718,12415,13153,13935,14764,15642,16572,17557,18601,19708,20879,
kshoji 0:831ef5c249ef 68 22121,23436,24830,26306
kshoji 0:831ef5c249ef 69 };
kshoji 0:831ef5c249ef 70 uint16_t mapMidi(float input) {
kshoji 0:831ef5c249ef 71 return midiTable[(int)(127.9 - input * 127.9)];
kshoji 0:831ef5c249ef 72 }
kshoji 0:831ef5c249ef 73
kshoji 0:831ef5c249ef 74 // Stepped Pentatonic mapping
kshoji 0:831ef5c249ef 75 //
kshoji 0:831ef5c249ef 76 uint16_t pentatonicTable[54] = {
kshoji 0:831ef5c249ef 77 0,19,22,26,29,32,38,43,51,58,65,77,86,103,115,129,154,173,206,231,259,308,346,
kshoji 0:831ef5c249ef 78 411,461,518,616,691,822,923,1036,1232,1383,1644,1845,2071,2463,2765,3288,
kshoji 0:831ef5c249ef 79 3691,4143,4927,5530,6577,7382,8286,9854,11060,13153,14764,16572,19708,22121,26306
kshoji 0:831ef5c249ef 80 };
kshoji 0:831ef5c249ef 81
kshoji 0:831ef5c249ef 82 uint16_t mapPentatonic(float input) {
kshoji 0:831ef5c249ef 83 uint8_t value = ((int)(1023.9 - input * 1023.9)) / (1024/53);
kshoji 0:831ef5c249ef 84 return pentatonicTable[value];
kshoji 0:831ef5c249ef 85 }
kshoji 0:831ef5c249ef 86
kshoji 0:831ef5c249ef 87 void updateLatestInputValue() {
kshoji 0:831ef5c249ef 88 // The loop is pretty simple - it just updates the parameters for the oscillators.
kshoji 0:831ef5c249ef 89 //
kshoji 0:831ef5c249ef 90 // Avoid using any functions that make extensive use of interrupts, or turn interrupts off.
kshoji 0:831ef5c249ef 91 // They will cause clicks and poops in the audio.
kshoji 0:831ef5c249ef 92
kshoji 1:a553c5d93bb8 93 #ifndef FEATURE_ORIGINAL_AUDUINO
kshoji 0:831ef5c249ef 94 // Smooth frequency mapping
kshoji 0:831ef5c249ef 95 syncPhaseInc = mapPhaseInc(SYNC_CONTROL) * 4.0;
kshoji 1:a553c5d93bb8 96 #endif
kshoji 0:831ef5c249ef 97
kshoji 0:831ef5c249ef 98 // Stepped mapping to MIDI notes: C, Db, D, Eb, E, F...
kshoji 0:831ef5c249ef 99 //syncPhaseInc = mapMidi(SYNC_CONTROL);
kshoji 0:831ef5c249ef 100
kshoji 1:a553c5d93bb8 101 #ifdef FEATURE_ORIGINAL_AUDUINO
kshoji 0:831ef5c249ef 102 // Stepped pentatonic mapping: D, E, G, A, B
kshoji 1:a553c5d93bb8 103 syncPhaseInc = mapPentatonic(SYNC_CONTROL);
kshoji 0:831ef5c249ef 104
kshoji 1:a553c5d93bb8 105 grainPhaseInc = mapPhaseInc(GRAIN_FREQ_CONTROL) * 2.0;
kshoji 1:a553c5d93bb8 106 grainDecay = GRAIN_DECAY_CONTROL * 128.0;
kshoji 1:a553c5d93bb8 107 grain2PhaseInc = mapPhaseInc(GRAIN2_FREQ_CONTROL) * 2.0;
kshoji 1:a553c5d93bb8 108 grain2Decay = GRAIN2_DECAY_CONTROL * 256.0;
kshoji 1:a553c5d93bb8 109 #else
kshoji 0:831ef5c249ef 110 grainPhaseInc = mapPhaseInc(GRAIN_FREQ_CONTROL) * 4.0;
kshoji 0:831ef5c249ef 111 grainDecay = GRAIN_DECAY_CONTROL * 16.0;
kshoji 0:831ef5c249ef 112 grain2PhaseInc = mapPhaseInc(GRAIN2_FREQ_CONTROL) * 4.0;
kshoji 0:831ef5c249ef 113 grain2Decay = GRAIN2_DECAY_CONTROL * 32.0;
kshoji 1:a553c5d93bb8 114 #endif
kshoji 0:831ef5c249ef 115 }
kshoji 0:831ef5c249ef 116
kshoji 0:831ef5c249ef 117 float adjustPhaseValue(float phaseAcc) {
kshoji 0:831ef5c249ef 118 float value = phaseAcc / 128.0;
kshoji 0:831ef5c249ef 119 value = ((value / 256.0) - (int)(value / 256.0)) * 256.0;
kshoji 0:831ef5c249ef 120 if (value > 256) value = 256;
kshoji 0:831ef5c249ef 121 if (phaseAcc > 32768) value = 256 - value;
kshoji 0:831ef5c249ef 122 return value;
kshoji 0:831ef5c249ef 123 }
kshoji 0:831ef5c249ef 124
kshoji 0:831ef5c249ef 125 void interruptHandler() {
kshoji 0:831ef5c249ef 126 float value;
kshoji 0:831ef5c249ef 127 float output;
kshoji 0:831ef5c249ef 128
kshoji 0:831ef5c249ef 129 updateLatestInputValue();
kshoji 0:831ef5c249ef 130
kshoji 0:831ef5c249ef 131 syncPhaseAcc += syncPhaseInc;
kshoji 0:831ef5c249ef 132 if (syncPhaseAcc > 65536.0) {
kshoji 0:831ef5c249ef 133 syncPhaseAcc -= 65536.0;
kshoji 0:831ef5c249ef 134 }
kshoji 0:831ef5c249ef 135 if (syncPhaseAcc < syncPhaseInc) {
kshoji 0:831ef5c249ef 136 // Time to start the next grain
kshoji 0:831ef5c249ef 137 grainPhaseAcc = 0;
kshoji 0:831ef5c249ef 138 grainAmp = 32768.0;
kshoji 0:831ef5c249ef 139 grain2PhaseAcc = 0;
kshoji 0:831ef5c249ef 140 grain2Amp = 32768.0;
kshoji 0:831ef5c249ef 141 LED_PIN = !LED_PIN;
kshoji 0:831ef5c249ef 142 }
kshoji 0:831ef5c249ef 143
kshoji 0:831ef5c249ef 144 // Increment the phase of the grain oscillators
kshoji 0:831ef5c249ef 145 grainPhaseAcc += grainPhaseInc;
kshoji 0:831ef5c249ef 146 grain2PhaseAcc += grain2PhaseInc;
kshoji 0:831ef5c249ef 147 if (grainPhaseAcc > 65536) grainPhaseAcc -= 65536;
kshoji 0:831ef5c249ef 148 if (grain2PhaseAcc > 65536) grain2PhaseAcc -= 65536;
kshoji 0:831ef5c249ef 149
kshoji 0:831ef5c249ef 150 // Convert phase into a triangle wave
kshoji 0:831ef5c249ef 151 value = adjustPhaseValue(grainPhaseAcc);
kshoji 0:831ef5c249ef 152 // Multiply by current grain amplitude to get sample
kshoji 0:831ef5c249ef 153 output = value * (grainAmp / 512.0);
kshoji 0:831ef5c249ef 154
kshoji 0:831ef5c249ef 155 // Repeat for second grain
kshoji 0:831ef5c249ef 156 value = adjustPhaseValue(grain2PhaseAcc);
kshoji 0:831ef5c249ef 157 output += value * (grain2Amp / 512.0);
kshoji 0:831ef5c249ef 158
kshoji 0:831ef5c249ef 159 // Make the grain amplitudes decay by a factor every sample (exponential decay)
kshoji 0:831ef5c249ef 160 grainAmp -= (grainAmp / 256.0) * grainDecay;
kshoji 0:831ef5c249ef 161 grain2Amp -= (grain2Amp / 256.0) * grain2Decay;
kshoji 0:831ef5c249ef 162
kshoji 0:831ef5c249ef 163 OUTPUT.write_u16(output);
kshoji 0:831ef5c249ef 164 }
kshoji 0:831ef5c249ef 165
kshoji 0:831ef5c249ef 166 int main() {
kshoji 0:831ef5c249ef 167 interrupt.attach_us(&interruptHandler, 32);
kshoji 0:831ef5c249ef 168 }