Kaoru Shoji
/
granularsynth
Auduino port
auduino.cpp
- Committer:
- kshoji
- Date:
- 2010-09-15
- Revision:
- 1:a553c5d93bb8
- Parent:
- 0:831ef5c249ef
File content as of revision 1:a553c5d93bb8:
#include <math.h> #include "mbed.h" #define FEATURE_ORIGINAL_AUDUINO // 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. #ifndef FEATURE_ORIGINAL_AUDUINO // Smooth frequency mapping syncPhaseInc = mapPhaseInc(SYNC_CONTROL) * 4.0; #endif // Stepped mapping to MIDI notes: C, Db, D, Eb, E, F... //syncPhaseInc = mapMidi(SYNC_CONTROL); #ifdef FEATURE_ORIGINAL_AUDUINO // Stepped pentatonic mapping: D, E, G, A, B syncPhaseInc = mapPentatonic(SYNC_CONTROL); grainPhaseInc = mapPhaseInc(GRAIN_FREQ_CONTROL) * 2.0; grainDecay = GRAIN_DECAY_CONTROL * 128.0; grain2PhaseInc = mapPhaseInc(GRAIN2_FREQ_CONTROL) * 2.0; grain2Decay = GRAIN2_DECAY_CONTROL * 256.0; #else 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; #endif } 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); }