Auduino port

Dependencies:   mbed

Revision:
0:831ef5c249ef
Child:
1:a553c5d93bb8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/auduino.cpp	Mon Sep 13 12:25:27 2010 +0000
@@ -0,0 +1,157 @@
+#include <math.h>
+#include "mbed.h"
+
+// Auduino for mbed
+// Ported and arranged by Kaoru Shoji
+
+// Original source code:
+// Auduino, the Lo-Fi granular synthesiser
+//
+// by Peter Knight, Tinker.it http://tinker.it
+//
+// Help:      http://code.google.com/p/tinkerit/wiki/Auduino
+// More help: http://groups.google.com/group/auduino
+//
+// Changelog:
+// 19 Nov 2008: Added support for ATmega8 boards
+// 21 Mar 2009: Added support for ATmega328 boards
+// 7 Apr 2009: Fixed interrupt vector for ATmega328 boards
+// 8 Apr 2009: Added support for ATmega1280 boards (Arduino Mega)
+
+// Analog in p16: Grain 1 pitch
+// Analog in p17: Grain 1 decay
+// Analog in p19: Grain 2 pitch
+// Analog in p20: Grain 2 decay
+// Analog in p15: Grain repetition frequency
+// Analog out p18: Audio out
+
+Ticker interrupt;
+AnalogIn SYNC_CONTROL(p15);
+AnalogIn GRAIN_FREQ_CONTROL(p16);
+AnalogIn GRAIN_DECAY_CONTROL(p17);
+AnalogIn GRAIN2_FREQ_CONTROL(p19);
+AnalogIn GRAIN2_DECAY_CONTROL(p20);
+AnalogOut OUTPUT(p18);
+DigitalOut LED_PIN(LED1);
+
+float syncPhaseAcc;
+float syncPhaseInc;
+
+float grainPhaseAcc;
+float grainPhaseInc;
+float grainAmp;
+float grainDecay;
+
+float grain2PhaseAcc;
+float grain2PhaseInc;
+float grain2Amp;
+float grain2Decay;
+
+// Smooth logarithmic mapping
+//
+float mapPhaseInc(double input) {
+  return pow(65536.0, 1.0 - input);
+}
+
+// Stepped chromatic mapping
+//
+uint16_t midiTable[] = {
+  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,
+  77,82,86,92,97,103,109,115,122,129,137,145,154,163,173,183,194,206,218,231,
+  244,259,274,291,308,326,346,366,388,411,435,461,489,518,549,581,616,652,691,
+  732,776,822,871,923,978,1036,1097,1163,1232,1305,1383,1465,1552,1644,1742,
+  1845,1955,2071,2195,2325,2463,2610,2765,2930,3104,3288,3484,3691,3910,4143,
+  4389,4650,4927,5220,5530,5859,6207,6577,6968,7382,7821,8286,8779,9301,9854,
+  10440,11060,11718,12415,13153,13935,14764,15642,16572,17557,18601,19708,20879,
+  22121,23436,24830,26306
+};
+uint16_t mapMidi(float input) {
+  return midiTable[(int)(127.9 - input * 127.9)];
+}
+
+// Stepped Pentatonic mapping
+//
+uint16_t pentatonicTable[54] = {
+  0,19,22,26,29,32,38,43,51,58,65,77,86,103,115,129,154,173,206,231,259,308,346,
+  411,461,518,616,691,822,923,1036,1232,1383,1644,1845,2071,2463,2765,3288,
+  3691,4143,4927,5530,6577,7382,8286,9854,11060,13153,14764,16572,19708,22121,26306
+};
+
+uint16_t mapPentatonic(float input) {
+  uint8_t value = ((int)(1023.9 - input * 1023.9)) / (1024/53);
+  return pentatonicTable[value];
+}
+
+void updateLatestInputValue() {
+  // The loop is pretty simple - it just updates the parameters for the oscillators.
+  //
+  // Avoid using any functions that make extensive use of interrupts, or turn interrupts off.
+  // They will cause clicks and poops in the audio.
+  
+  // Smooth frequency mapping
+  syncPhaseInc = mapPhaseInc(SYNC_CONTROL) * 4.0;
+  
+  // Stepped mapping to MIDI notes: C, Db, D, Eb, E, F...
+  //syncPhaseInc = mapMidi(SYNC_CONTROL);
+  
+  // Stepped pentatonic mapping: D, E, G, A, B
+  //syncPhaseInc = mapPentatonic(SYNC_CONTROL);
+
+  grainPhaseInc  = mapPhaseInc(GRAIN_FREQ_CONTROL) * 4.0;
+  grainDecay     = GRAIN_DECAY_CONTROL * 16.0;
+  grain2PhaseInc = mapPhaseInc(GRAIN2_FREQ_CONTROL) * 4.0;
+  grain2Decay    = GRAIN2_DECAY_CONTROL * 32.0;
+}
+
+float adjustPhaseValue(float phaseAcc) {
+  float value = phaseAcc / 128.0;
+  value = ((value / 256.0) - (int)(value / 256.0)) * 256.0;
+  if (value > 256) value = 256;
+  if (phaseAcc > 32768) value = 256 - value;
+  return value;
+}
+
+void interruptHandler() {
+  float value;
+  float output;
+  
+  updateLatestInputValue();
+
+  syncPhaseAcc += syncPhaseInc;
+  if (syncPhaseAcc > 65536.0) {
+    syncPhaseAcc -= 65536.0;
+  }
+  if (syncPhaseAcc < syncPhaseInc) {
+    // Time to start the next grain
+    grainPhaseAcc = 0;
+    grainAmp = 32768.0;
+    grain2PhaseAcc = 0;
+    grain2Amp = 32768.0;
+    LED_PIN = !LED_PIN;
+  }
+  
+  // Increment the phase of the grain oscillators
+  grainPhaseAcc += grainPhaseInc;
+  grain2PhaseAcc += grain2PhaseInc;
+  if (grainPhaseAcc > 65536) grainPhaseAcc -= 65536;
+  if (grain2PhaseAcc > 65536) grain2PhaseAcc -= 65536;
+
+  // Convert phase into a triangle wave
+  value = adjustPhaseValue(grainPhaseAcc);
+  // Multiply by current grain amplitude to get sample
+  output = value * (grainAmp / 512.0);
+
+  // Repeat for second grain
+  value = adjustPhaseValue(grain2PhaseAcc);
+  output += value * (grain2Amp / 512.0);
+
+  // Make the grain amplitudes decay by a factor every sample (exponential decay)
+  grainAmp -= (grainAmp / 256.0) * grainDecay;
+  grain2Amp -= (grain2Amp / 256.0) * grain2Decay;
+
+  OUTPUT.write_u16(output);
+}
+
+int main() {
+  interrupt.attach_us(&interruptHandler, 32);
+}