0

I am fairly new to programming, and as I have a fascination for music I thought to start with building a simple sequencer using codes from the web.

Now I found a perfect code but somehow it does not behave as it needs to and I hope to get some advice here in order to learn more and eventually build my own synthesizer!

/* analog inputs:
 * A0 pitch step 1 (syncPhaseInc)
 * A1 pitch step 2
 * A2 pitch step 3
 * A3 pitch step 4
 * A4 tempo
 * A5 effect (grainPhaseInc)
 * plus volume potentiometer
 *
 * audio out via 220 ohm resistor to 3.5mm jack
 * audio out via 10K/10K voltage divider and 10K volume pot and 10uF cap to internal mono amp with speaker
 * power switch on amp
 * built with Arduino Nano on perf board powered by USB cable
 */

#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;

// 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__) || defined(__AVR_ATmega2560__)
 //
 // 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
 }

long counter = 0;
 long tempo;
 int pattern = 0;

const byte pat0 = 4;
 const byte pat1 = 5;
 const byte pat2 = 6;
 const byte pat3 = 7;

void setup() {
 pinMode(PWM_PIN, OUTPUT);
 audioOn();
 pinMode(LED_PIN, OUTPUT);

pinMode(pat0, OUTPUT);
 pinMode(pat1, OUTPUT);
 pinMode(pat2, OUTPUT);
 pinMode(pat3, OUTPUT);
 digitalWrite(pat0, LOW);
 digitalWrite(pat1, LOW);
 digitalWrite(pat2, LOW);
 digitalWrite(pat3, LOW);

// presets for 3 less important pots
 grainDecay = 200 / 8;
 grain2PhaseInc = mapPhaseInc(200) / 2;
 grain2Decay = 200 / 4;
 }

void loop() {

tempo = map(analogRead(A4), 0, 1023, 100, 4000);
 counter++;
 if (counter > tempo) {
 counter = 0;
 if (pattern == 4) {
 pattern = 0;
 }
 switch (pattern) {
 case 0:
 syncPhaseInc = mapPentatonic(analogRead(A0));
 digitalWrite(pat3, LOW);
 digitalWrite(pat0, HIGH);
 break;
 case 1:
 syncPhaseInc = mapPentatonic(analogRead(A1));
 digitalWrite(pat0, LOW);
 digitalWrite(pat1, HIGH);
 break;
 case 2:
 syncPhaseInc = mapPentatonic(analogRead(A2));
 digitalWrite(pat1, LOW);
 digitalWrite(pat2, HIGH);
 break;
 case 3:
 syncPhaseInc = mapPentatonic(analogRead(A3));
 digitalWrite(pat2, LOW);
 digitalWrite(pat3, HIGH);
 break;
 }

grainPhaseInc = mapPhaseInc(analogRead(A5)) / 2;
 pattern++;
 }
 }

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;
 }
  • one thing I cannot explain is that the sound output pin is different from the one in the code. The code states that the output pin is PWM 3 for an ATmega328 which I use, but the sound from this pin is SUPER soft and noisy when I amplify the sound with an amplifier chip.
  • PWM 13 produces clean and loud sound, but putting filters and effects over the sound does not seem to work.

Does somebody know why this is the case? I would really like to use effects over the sounds. Because what is a synthesizer without awesome effects?!

Thanks in advance !!

  • " I thought to start with building a simple sequencer using codes from the web." That's fine but next step after this is to understand code that you copied. At the beginning you should cut out code that you dont need. – dunajski Jan 29 '19 at 08:10
  • Do you know which Arduino board you are using? It looks like if you have a Arduino Mega, PWM 13 is the correct pin. – Spinnaker Jan 29 '19 at 20:56
  • @Kyle No I am using an Uno.. – Jolie Smets Jan 30 '19 at 09:28

0 Answers0