Permalink
Browse files

arduino synth

  • Loading branch information...
1 parent a1d001a commit 43e67a12a7f1de0d963ceaea5f73b4adf1b47947 @Lessnullvoid committed May 12, 2012
Showing with 240 additions and 0 deletions.
  1. +208 −0 DMD_01/arduino/auduino_v5/auduino_v5.ino
  2. +32 −0 DMD_01/arduino/sinteMini/sinteMini.ino
@@ -0,0 +1,208 @@
+// 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
+//
+// Analog in 0: Grain 1 pitch
+// Analog in 1: Grain 2 decay
+// Analog in 2: Grain 1 decay
+// Analog in 3: Grain 2 pitch
+// Analog in 4: Grain repetition frequency
+//
+// Digital 3: Audio out (Digital 11 on ATmega8)
+//
+// 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)
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+uint16_t syncPhaseAcc;
+uint16_t syncPhaseInc;
+uint16_t grainPhaseAcc;
+uint16_t grainPhaseInc;
+uint16_t grainAmp;
+uint8_t grainDecay;
+uint16_t grain2PhaseAcc;
+uint16_t grain2PhaseInc;
+uint16_t grain2Amp;
+uint8_t grain2Decay;
+
+// Map Analogue channels
+#define SYNC_CONTROL (4)
+#define GRAIN_FREQ_CONTROL (0)
+#define GRAIN_DECAY_CONTROL (2)
+#define GRAIN2_FREQ_CONTROL (3)
+#define GRAIN2_DECAY_CONTROL (1)
+
+
+// Changing these will also requires rewriting audioOn()
+
+#if defined(__AVR_ATmega8__)
+//
+// On old ATmega8 boards.
+// Output is on pin 11
+//
+#define LED_PIN 13
+#define LED_PORT PORTB
+#define LED_BIT 5
+#define PWM_PIN 11
+#define PWM_VALUE OCR2
+#define PWM_INTERRUPT TIMER2_OVF_vect
+#elif defined(__AVR_ATmega1280__)
+//
+// On the Arduino Mega
+// Output is on pin 3
+//
+#define LED_PIN 13
+#define LED_PORT PORTB
+#define LED_BIT 7
+#define PWM_PIN 3
+#define PWM_VALUE OCR3C
+#define PWM_INTERRUPT TIMER3_OVF_vect
+#else
+//
+// For modern ATmega168 and ATmega328 boards
+// Output is on pin 3
+//
+#define PWM_PIN 3
+#define PWM_VALUE OCR2B
+#define LED_PIN 13
+#define LED_PORT PORTB
+#define LED_BIT 5
+#define PWM_INTERRUPT TIMER2_OVF_vect
+#endif
+
+// Smooth logarithmic mapping
+//
+uint16_t antilogTable[] = {
+ 64830,64132,63441,62757,62081,61413,60751,60097,59449,58809,58176,57549,56929,56316,55709,55109,
+ 54515,53928,53347,52773,52204,51642,51085,50535,49991,49452,48920,48393,47871,47356,46846,46341,
+ 45842,45348,44859,44376,43898,43425,42958,42495,42037,41584,41136,40693,40255,39821,39392,38968,
+ 38548,38133,37722,37316,36914,36516,36123,35734,35349,34968,34591,34219,33850,33486,33125,32768
+};
+uint16_t mapPhaseInc(uint16_t input) {
+ return (antilogTable[input & 0x3f]) >> (input >> 6);
+}
+
+// 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(uint16_t input) {
+ return (midiTable[(1023-input) >> 3]);
+}
+
+// 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(uint16_t input) {
+ uint8_t value = (1023-input) / (1024/53);
+ return (pentatonicTable[value]);
+}
+
+
+void audioOn() {
+#if defined(__AVR_ATmega8__)
+ // ATmega8 has different registers
+ TCCR2 = _BV(WGM20) | _BV(COM21) | _BV(CS20);
+ TIMSK = _BV(TOIE2);
+#elif defined(__AVR_ATmega1280__)
+ TCCR3A = _BV(COM3C1) | _BV(WGM30);
+ TCCR3B = _BV(CS30);
+ TIMSK3 = _BV(TOIE3);
+#else
+ // Set up PWM to 31.25kHz, phase accurate
+ TCCR2A = _BV(COM2B1) | _BV(WGM20);
+ TCCR2B = _BV(CS20);
+ TIMSK2 = _BV(TOIE2);
+#endif
+}
+
+
+void setup() {
+ pinMode(PWM_PIN,OUTPUT);
+ audioOn();
+ pinMode(LED_PIN,OUTPUT);
+}
+
+void loop() {
+ // 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(analogRead(SYNC_CONTROL)) / 4;
+
+ // Stepped mapping to MIDI notes: C, Db, D, Eb, E, F...
+ //syncPhaseInc = mapMidi(analogRead(SYNC_CONTROL));
+
+ // Stepped pentatonic mapping: D, E, G, A, B
+ syncPhaseInc = mapPentatonic(analogRead(SYNC_CONTROL));
+
+ grainPhaseInc = mapPhaseInc(analogRead(GRAIN_FREQ_CONTROL)) / 2;
+ grainDecay = analogRead(GRAIN_DECAY_CONTROL) / 8;
+ grain2PhaseInc = mapPhaseInc(analogRead(GRAIN2_FREQ_CONTROL)) / 2;
+ grain2Decay = analogRead(GRAIN2_DECAY_CONTROL) / 4;
+}
+
+SIGNAL(PWM_INTERRUPT)
+{
+ uint8_t value;
+ uint16_t output;
+
+ syncPhaseAcc += syncPhaseInc;
+ if (syncPhaseAcc < syncPhaseInc) {
+ // Time to start the next grain
+ grainPhaseAcc = 0;
+ grainAmp = 0x7fff;
+ grain2PhaseAcc = 0;
+ grain2Amp = 0x7fff;
+ LED_PORT ^= 1 << LED_BIT; // Faster than using digitalWrite
+ }
+
+ // Increment the phase of the grain oscillators
+ grainPhaseAcc += grainPhaseInc;
+ grain2PhaseAcc += grain2PhaseInc;
+
+ // Convert phase into a triangle wave
+ value = (grainPhaseAcc >> 7) & 0xff;
+ if (grainPhaseAcc & 0x8000) value = ~value;
+ // Multiply by current grain amplitude to get sample
+ output = value * (grainAmp >> 8);
+
+ // Repeat for second grain
+ value = (grain2PhaseAcc >> 7) & 0xff;
+ if (grain2PhaseAcc & 0x8000) value = ~value;
+ output += value * (grain2Amp >> 8);
+
+ // Make the grain amplitudes decay by a factor every sample (exponential decay)
+ grainAmp -= (grainAmp >> 8) * grainDecay;
+ grain2Amp -= (grain2Amp >> 8) * grain2Decay;
+
+ // Scale output to the available range, clipping if necessary
+ output >>= 9;
+ if (output > 255) output = 255;
+
+ // Output to PWM (this is faster than using analogWrite)
+ PWM_VALUE = output;
+}
@@ -0,0 +1,32 @@
+#define DIV_PIN 5
+#define FREQ_PIN 4
+#define DUTY_PIN 3
+
+void setup(){
+ pinMode(3, OUTPUT);
+ pinMode(11, OUTPUT);
+ TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20);
+}
+
+// accepts values 1-7 to set prescalers 1/8/32/64/128/256/1024
+// 0 turns timer off
+void setPrescaler(uint8_t divisor){
+ if(divisor > 7)
+ return;
+ TCCR2B = _BV(WGM22) | divisor;
+}
+
+// expects a value 0.0-1.0
+void setDutyCycle(float value){
+ OCR2B = OCR2A * value;
+}
+
+void setTopLimit(uint8_t limit){
+ OCR2A = limit;
+}
+
+void loop(){
+ setPrescaler(analogRead(DIV_PIN)>>7);
+ setTopLimit(analogRead(FREQ_PIN)>>2);
+ setDutyCycle((float)analogRead(DUTY_PIN)/1023.0);
+}

0 comments on commit 43e67a1

Please sign in to comment.