// SeqDuino, Auduino based synthesizer with 16 step sequencer. // // Original Auduino, the Lo-Fi granular synthesiser // by Peter Knight, Tinker.it http://tinker.it // // MIDI Clock Reciver and Step Sequencer // by "Yamadanohito". // This program is tested on only ATMEGA328(Arduino Duemilanove). // CAUTION!: If you use this program with KORG Electribe or some other // MIDI instrument with "Heavy" MIDI traffic, Plese set MIDI Send filter. // This program need MIDI START/STOP/CONTINUE message only. // Analogs. // 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 // Analog in 5: Scale select. #include #include 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) #define SELECTER_IN (5) // Map Digital channels #define SEQ_DATA1 (8) #define SEQ_DATA2 (9) #define SEQ_DATA3 (10) #define SEQ_DATA4 (11) // 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 uint16_t scale_selector; // Scale selector data. uint16_t incomingData = 0; // MIDI incoming data. uint16_t clock_div = 6; // MIDI Clock tick divider. uint16_t step_cnt =0; // Sequencer step counter. Using least 4bit(A0 to A3). uint16_t state = 0; // Sequencer running status. 1=run. uint16_t tmp_read; // Temporaly read buffer. //Scale Selector Switch Table. uint16_t SelectTable[] = { 0,1,2,3,4,5,6,7,8,9,10,11,11 }; // 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[1023-(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[(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 octaveTable[54] = { 0,17,34,69,137,274,549,1097,2195,4389,8779,17557 }; uint16_t minPentaTable[55] = { 0, 17, 20, 23, 26, 31, 34, 41, 46, 51, 61, 69, 82, 92, 103, 122, 137, 163, 183, 206, 244, 274, 326, 366, 411, 489, 549, 652, 732, 822, 978, 1097, 1305, 1465, 1644, 1955, 2195, 2610, 2930, 3288, 3910, 4389, 5220, 5859, 6577, 7821, 8779, 10440, 11718, 13153, 15642, 17557, 20879, 23436, 26306 }; uint16_t majPentaTable[55] = { 0, 17, 19, 22, 26, 29, 34, 38, 43, 51, 58, 69, 77, 86, 103, 115, 137, 154, 173, 206, 231, 274, 308, 346, 411, 461, 549, 616, 691, 822, 923, 1097, 1232, 1383, 1644, 1845, 2195, 2463, 2765, 3288, 3691, 4389, 4927, 5530, 6577, 7382, 8779, 9854, 11060, 13153, 14764, 17557, 19708, 22121, 26306 }; uint16_t min3rdTable[55] = { 0, 17, 20, 24, 29, 34, 41, 48, 58, 69, 82, 97, 115, 137, 163, 194, 231, 274, 326, 388, 461, 549, 652, 776, 923, 1097, 1305, 1552, 1845, 2195, 2610, 3104, 3691, 4389, 5220, 6207, 7382, 8779, 10440, 12415, 14764, 17557, 20879, 24830 }; uint16_t maj3rdTable[34] = { 0, 17, 22, 27, 34, 43, 54, 69, 86, 109, 137, 173, 218, 274, 346, 435, 549, 691, 871, 1097, 1383, 1742, 2195, 2765, 3484, 4389, 5530, 6968, 8779, 11060, 13935, 17557, 22121 }; uint16_t FourthTable[34] = { 0, 17, 23, 31, 34, 46, 61, 69, 92, 122, 137, 183, 244, 274, 366, 489, 549, 732, 978, 1097, 1465, 1955, 2195, 2930, 3910, 4389, 5859, 7821, 8779, 11718, 15642, 17557, 23436 }; uint16_t FifthTable[24] = { 0, 17, 26, 34, 51, 69, 103, 137, 206, 274, 411, 549, 822, 1097, 1644, 2195, 3288, 4389, 6577, 8779, 13153, 17557, 26306 }; uint16_t LydianTable[76] = { 0, 17, 19, 22, 24, 26, 29, 32, 34, 38, 43, 48, 51, 58, 65, 69, 77, 86, 97, 103, 115, 129, 137, 154, 173, 194, 206, 231, 259, 274, 308, 346, 388, 411, 461, 518, 549, 616, 691, 776, 822, 923, 1036, 1097, 1232, 1383, 1552,1644, 1845, 2071, 2195, 2463, 2765, 3104, 3288, 3691, 4143, 4389, 4927, 5530, 6207, 6577, 7382, 8286, 8779, 9854, 11060, 12415, 13153, 14764, 16572, 17557, 19708, 22121, 24830, 26306 }; uint16_t RyukyuTable[55] = { 0, 17, 22, 23, 26, 32, 34, 43, 46, 51, 65, 69, 86, 92, 103, 129, 137, 173, 183, 206, 259, 274, 346, 366, 411, 518, 549, 691, 732, 822, 1036, 1097, 1383, 1465, 1644, 2071, 2195, 2765, 2930, 3288, 4143, 4389, 5530, 5859, 6577, 8286, 8779, 11060, 11718, 13153, 16572, 17557, 22121, 23436, 26306 }; uint16_t DimTable[86]={ 0, 17, 19, 20, 23, 24, 27, 29, 32, 34, 38, 41, 46, 48, 54, 58, 65, 69, 77, 82, 92, 97, 109, 115, 129, 137, 154, 163, 183, 194, 218, 231, 259, 274, 308, 326, 366, 388, 435, 461, 518, 549, 616, 652, 732, 776, 871, 923, 1036, 1097, 1232, 1305, 1465, 1552, 1742, 1845, 2071, 2195, 2463, 2610, 2930, 3104, 3484, 3691, 4143, 4389, 4927, 5220, 5859, 6207, 6968, 7382, 8286, 8779, 9854, 10440, 11718,12415, 13935, 14764, 16572, 17557, 19708, 20879, 23436, 24830 }; uint16_t cheetaTable[65]={ 0, 17, 20, 23, 24, 27, 31, 34, 41, 46, 48, 54, 61, 69, 82, 92, 97, 109, 122, 137, 163, 183, 194, 218, 244, 274, 326, 366, 388, 435, 489, 549, 652, 732, 776, 871, 978, 1097, 1305, 1465, 1552, 1742, 1955, 2195, 2610, 2930, 3104, 3484, 3910, 4389, 5220, 5859, 6207, 6968, 7821, 8779, 10440, 11718, 12415, 13935, 15642, 17557, 20879, 23436, 24830 }; uint16_t ScaleSelect(uint16_t input) { uint8_t value = (input) / (1024/12); return (SelectTable[value]); } uint16_t mapPentatonic(uint16_t input) { uint8_t value = (input) / (1024/53); return (pentatonicTable[value]); } uint16_t mapOctave(uint16_t input) { uint8_t value = (input) / (1024/11); return(octaveTable[value]); } uint16_t mapMinPenta(uint16_t input) { uint8_t value = (input) / (1024/54); return (minPentaTable[value]); } uint16_t mapMajPenta(uint16_t input) { uint8_t value = (input) / (1024/54); return (majPentaTable[value]); } uint16_t mapMin3rd(uint16_t input) { uint8_t value = (input) / (1024/44); return (min3rdTable[value]); } uint16_t mapMaj3rd(uint16_t input) { uint8_t value = (input) / (1024/32); return (maj3rdTable[value]); } uint16_t map4th(uint16_t input) { uint8_t value = (input) / (1024/32); return (FourthTable[value]); } uint16_t map5th(uint16_t input) { uint8_t value = (input) / (1024/22); return (FifthTable[value]); } uint16_t mapLydian(uint16_t input) { uint8_t value = (input) / (1024/75); return (LydianTable[value]); } uint16_t mapDim(uint16_t input) { uint8_t value = (input) / (1024/85); return(DimTable[value]); } uint16_t mapRyukyu(uint16_t input) { uint8_t value = (input) / (1024/54); return(RyukyuTable[value]); } uint16_t mapCheeta(uint16_t input) { uint8_t value = (input) / (1024/55); return(cheetaTable[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); // Sequencer address data out. pinMode(SEQ_DATA1, OUTPUT); pinMode(SEQ_DATA2, OUTPUT); pinMode(SEQ_DATA3, OUTPUT); pinMode(SEQ_DATA4, OUTPUT); // Set address data to ALL 0s. digitalWrite(SEQ_DATA1, LOW); digitalWrite(SEQ_DATA2, LOW); digitalWrite(SEQ_DATA3, LOW); digitalWrite(SEQ_DATA4, LOW); Serial.begin(31250); } void loop() { if(Serial.available()){ incomingData = Serial.read(); if(incomingData == 0xf8){ //MIDI CLOCK if( state == 1 ){ // Running if( clock_div == 6 ){ // 24 tick = 1 note(4 seq steps). 16 step = 96 tick. // Write Sequence step data to A0 to A3. if((step_cnt&0x01)!=0) digitalWrite(SEQ_DATA1, HIGH); else digitalWrite(SEQ_DATA1, LOW); if((step_cnt&0x02)!=0) digitalWrite(SEQ_DATA2, HIGH); else digitalWrite(SEQ_DATA2, LOW); if((step_cnt&0x04)!=0) digitalWrite(SEQ_DATA3, HIGH); else digitalWrite(SEQ_DATA3, LOW); if((step_cnt&0x08)!=0) digitalWrite(SEQ_DATA4, HIGH); else digitalWrite(SEQ_DATA4, LOW); //Forward (CW) step_cnt++; //Reverse (CCW) //step_cnt--; } } // When not Running, but count clock. clock_div--; if( clock_div == 0) clock_div=6; } else if( incomingData == 0xfa) { //MIDI START step_cnt = 0; //Reset start position (Step 1) clock_div = 6; //Reset clock tick. state = 1; //Set to run state. } else if( incomingData == 0xfc) { //MIDI STOP state = 0; //Set to stop state. } else if( incomingData == 0xfb) { //MIDI CONTINUE state = 1; //Set to run state. clock_div =6; //Reset clock tick. } else { //Any other data, will flush serial buffer Serial.flush(); } } // Read Note data tmp_read = analogRead(SYNC_CONTROL); // Select Scale switch (scale_selector) { case 0: syncPhaseInc = mapCheeta(tmp_read); break; case 1: syncPhaseInc = mapOctave(tmp_read); break; case 2: syncPhaseInc = mapMinPenta(tmp_read); break; case 3: syncPhaseInc = mapMajPenta(tmp_read); break; case 4: syncPhaseInc = mapMin3rd(tmp_read); break; case 5: syncPhaseInc = mapMaj3rd(tmp_read); break; case 6: syncPhaseInc = map4th(tmp_read); break; case 7: syncPhaseInc = map5th(tmp_read); break; case 8: syncPhaseInc = mapLydian(tmp_read); break; case 9: syncPhaseInc = mapDim(tmp_read); break; case 10: syncPhaseInc = mapRyukyu(tmp_read); break; case 11: default: syncPhaseInc = mapMidi(tmp_read); } // Read Scale selector scale_selector = ScaleSelect( analogRead(SELECTER_IN)); // Raed synth data 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; }