Auduino port

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers auduino.cpp Source File

auduino.cpp

00001 #include <math.h>
00002 #include "mbed.h"
00003 
00004 #define FEATURE_ORIGINAL_AUDUINO
00005 
00006 // Auduino for mbed
00007 // Ported and arranged by Kaoru Shoji
00008 
00009 // Original source code:
00010 // Auduino, the Lo-Fi granular synthesiser
00011 //
00012 // by Peter Knight, Tinker.it http://tinker.it
00013 //
00014 // Help:      http://code.google.com/p/tinkerit/wiki/Auduino
00015 // More help: http://groups.google.com/group/auduino
00016 //
00017 // Changelog:
00018 // 19 Nov 2008: Added support for ATmega8 boards
00019 // 21 Mar 2009: Added support for ATmega328 boards
00020 // 7 Apr 2009: Fixed interrupt vector for ATmega328 boards
00021 // 8 Apr 2009: Added support for ATmega1280 boards (Arduino Mega)
00022 
00023 // Analog in p16: Grain 1 pitch
00024 // Analog in p17: Grain 1 decay
00025 // Analog in p19: Grain 2 pitch
00026 // Analog in p20: Grain 2 decay
00027 // Analog in p15: Grain repetition frequency
00028 // Analog out p18: Audio out
00029 
00030 Ticker interrupt;
00031 AnalogIn SYNC_CONTROL(p15);
00032 AnalogIn GRAIN_FREQ_CONTROL(p16);
00033 AnalogIn GRAIN_DECAY_CONTROL(p17);
00034 AnalogIn GRAIN2_FREQ_CONTROL(p19);
00035 AnalogIn GRAIN2_DECAY_CONTROL(p20);
00036 AnalogOut OUTPUT(p18);
00037 DigitalOut LED_PIN(LED1);
00038 
00039 float syncPhaseAcc;
00040 float syncPhaseInc;
00041 
00042 float grainPhaseAcc;
00043 float grainPhaseInc;
00044 float grainAmp;
00045 float grainDecay;
00046 
00047 float grain2PhaseAcc;
00048 float grain2PhaseInc;
00049 float grain2Amp;
00050 float grain2Decay;
00051 
00052 // Smooth logarithmic mapping
00053 //
00054 float mapPhaseInc(double input) {
00055   return pow(65536.0, 1.0 - input);
00056 }
00057 
00058 // Stepped chromatic mapping
00059 //
00060 uint16_t midiTable[] = {
00061   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,
00062   77,82,86,92,97,103,109,115,122,129,137,145,154,163,173,183,194,206,218,231,
00063   244,259,274,291,308,326,346,366,388,411,435,461,489,518,549,581,616,652,691,
00064   732,776,822,871,923,978,1036,1097,1163,1232,1305,1383,1465,1552,1644,1742,
00065   1845,1955,2071,2195,2325,2463,2610,2765,2930,3104,3288,3484,3691,3910,4143,
00066   4389,4650,4927,5220,5530,5859,6207,6577,6968,7382,7821,8286,8779,9301,9854,
00067   10440,11060,11718,12415,13153,13935,14764,15642,16572,17557,18601,19708,20879,
00068   22121,23436,24830,26306
00069 };
00070 uint16_t mapMidi(float input) {
00071   return midiTable[(int)(127.9 - input * 127.9)];
00072 }
00073 
00074 // Stepped Pentatonic mapping
00075 //
00076 uint16_t pentatonicTable[54] = {
00077   0,19,22,26,29,32,38,43,51,58,65,77,86,103,115,129,154,173,206,231,259,308,346,
00078   411,461,518,616,691,822,923,1036,1232,1383,1644,1845,2071,2463,2765,3288,
00079   3691,4143,4927,5530,6577,7382,8286,9854,11060,13153,14764,16572,19708,22121,26306
00080 };
00081 
00082 uint16_t mapPentatonic(float input) {
00083   uint8_t value = ((int)(1023.9 - input * 1023.9)) / (1024/53);
00084   return pentatonicTable[value];
00085 }
00086 
00087 void updateLatestInputValue() {
00088   // The loop is pretty simple - it just updates the parameters for the oscillators.
00089   //
00090   // Avoid using any functions that make extensive use of interrupts, or turn interrupts off.
00091   // They will cause clicks and poops in the audio.
00092   
00093 #ifndef FEATURE_ORIGINAL_AUDUINO
00094   // Smooth frequency mapping
00095   syncPhaseInc = mapPhaseInc(SYNC_CONTROL) * 4.0;
00096 #endif
00097   
00098   // Stepped mapping to MIDI notes: C, Db, D, Eb, E, F...
00099   //syncPhaseInc = mapMidi(SYNC_CONTROL);
00100   
00101 #ifdef FEATURE_ORIGINAL_AUDUINO
00102   // Stepped pentatonic mapping: D, E, G, A, B
00103   syncPhaseInc = mapPentatonic(SYNC_CONTROL);
00104 
00105   grainPhaseInc  = mapPhaseInc(GRAIN_FREQ_CONTROL) * 2.0;
00106   grainDecay     = GRAIN_DECAY_CONTROL * 128.0;
00107   grain2PhaseInc = mapPhaseInc(GRAIN2_FREQ_CONTROL) * 2.0;
00108   grain2Decay    = GRAIN2_DECAY_CONTROL * 256.0;
00109 #else
00110   grainPhaseInc  = mapPhaseInc(GRAIN_FREQ_CONTROL) * 4.0;
00111   grainDecay     = GRAIN_DECAY_CONTROL * 16.0;
00112   grain2PhaseInc = mapPhaseInc(GRAIN2_FREQ_CONTROL) * 4.0;
00113   grain2Decay    = GRAIN2_DECAY_CONTROL * 32.0;
00114 #endif
00115 }
00116 
00117 float adjustPhaseValue(float phaseAcc) {
00118   float value = phaseAcc / 128.0;
00119   value = ((value / 256.0) - (int)(value / 256.0)) * 256.0;
00120   if (value > 256) value = 256;
00121   if (phaseAcc > 32768) value = 256 - value;
00122   return value;
00123 }
00124 
00125 void interruptHandler() {
00126   float value;
00127   float output;
00128   
00129   updateLatestInputValue();
00130 
00131   syncPhaseAcc += syncPhaseInc;
00132   if (syncPhaseAcc > 65536.0) {
00133     syncPhaseAcc -= 65536.0;
00134   }
00135   if (syncPhaseAcc < syncPhaseInc) {
00136     // Time to start the next grain
00137     grainPhaseAcc = 0;
00138     grainAmp = 32768.0;
00139     grain2PhaseAcc = 0;
00140     grain2Amp = 32768.0;
00141     LED_PIN = !LED_PIN;
00142   }
00143   
00144   // Increment the phase of the grain oscillators
00145   grainPhaseAcc += grainPhaseInc;
00146   grain2PhaseAcc += grain2PhaseInc;
00147   if (grainPhaseAcc > 65536) grainPhaseAcc -= 65536;
00148   if (grain2PhaseAcc > 65536) grain2PhaseAcc -= 65536;
00149 
00150   // Convert phase into a triangle wave
00151   value = adjustPhaseValue(grainPhaseAcc);
00152   // Multiply by current grain amplitude to get sample
00153   output = value * (grainAmp / 512.0);
00154 
00155   // Repeat for second grain
00156   value = adjustPhaseValue(grain2PhaseAcc);
00157   output += value * (grain2Amp / 512.0);
00158 
00159   // Make the grain amplitudes decay by a factor every sample (exponential decay)
00160   grainAmp -= (grainAmp / 256.0) * grainDecay;
00161   grain2Amp -= (grain2Amp / 256.0) * grain2Decay;
00162 
00163   OUTPUT.write_u16(output);
00164 }
00165 
00166 int main() {
00167   interrupt.attach_us(&interruptHandler, 32);
00168 }