Realizzare un Arduino DIY synth

Reading Time: 3 minutes

Come realizzare un semplice e leggero synth basato su Arduino per poter suonare ovunque. Con questo esempio potrai creare uno strumento con un oscillatore audio con controllo del tremolo, del vibrato e della frequenza di un filtro bassa banda.

In questo esempio mostriamo come realizzare un semplice synth DIY utilizzando Arduino e Mozzi (Sound Synthesis Library for Arduino).

Il circuito è realizzato utilizzando sei potenziometri connessi agli ingressi analogici di Arduino (A0-A5) e l’uscita audio connessa alla porta digitale numero 9.

Il primo potenziometro viene utilizzato per controllare la frequenza dell’oscillatore che crea un segnale caratterizzato da un’onda a dente di sega, il secondo controlla la frequenza del LFO che genera il tremolo, il terzo cambia la profondità del tremolo (depth). Il quarto e il quinto potenziometro controllano la frequenza e la quantità (depth) del LFO che genera il vibrato. Infine, il sesto potenziometro controlla la frequenza centrale di un filtro passa banda usato per filtrare il segnale prodotto dall’oscillatore audio.

In questo video, realizzato nella primavera del 2017 in occasione di Invasioni Digitali a Cosenza, siamo andati a suonare all’interna del parco della Villa Vecchia.

Il codice

/*  DP Synth-01 - One audio oscillator with BP Filter, tremolo and vibrato control
  
    This example code is in the public domain.

    Artis Lab - 2017
    www.artislab.it
    info@artislab.it
*/

#include <Oscil.h>; // oscillator template
#include <StateVariable.h>;

#include <tables/sin2048_int8.h>; // sine table for oscillator
#include <tables/saw2048_int8.h>; //sawtoth table
//#include <tables/square_no_alias_2048_int8.h>; //square table
//#include <tables/triangle2048_int8.h>; //triangle table

// audio oscillator 
Oscil <SAW2048_NUM_CELLS, AUDIO_RATE> aOscil(SAW2048_DATA);
// audio oscillators for tremelo and vibrato
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aTremolo(SIN2048_DATA);
Oscil <SIN2048_NUM_CELLS, AUDIO_RATE> aVibrato(SIN2048_DATA);
//LowPassFilter lpf;
StateVariable <BANDPASS> svf; // can be LOWPASS, BANDPASS, HIGHPASS or NOTCH

// use #define for CONTROL_RATE, not a constant
#define CONTROL_RATE 64 // powers of 2 please

const char FREQ_PIN = 0; // set the input for the Frequency to analog pin 0
const char TREM_PIN = 1;
const char TREMDEP_PIN =2;
const char VIB_PIN =3;
const char VIBDEP_PIN =4;
const char FILTER_PIN = 5; // set the input for the filter cutoff to analog pin 5

byte VibratoDepth=0;
byte TremoloDepth=0;
float alpha = 0.5;
int FreqValue=0;
int CutOffValue=0;
int TremValue=0;
int VibValue=0;
int TremDepValue=0;
int VibDepValue=0;

void setup(){
  startMozzi(CONTROL_RATE); // set a control rate of 64 (powers of 2 please)
  svf.setResonance(120);
  svf.setCentreFreq(2000);
}


void updateControl(){

  int FreqKnob = mozziAnalogRead(FREQ_PIN); // value is 0-1023
  //We use a running average filter to smooth the sensor input
  FreqValue =alpha * FreqKnob + (1. - alpha) * FreqValue;
  Q24n8 oscFreq=float_to_Q24n8(40*pow(10,FreqValue/475.));
  aOscil.setFreq_Q24n8(oscFreq); // set the frequency
   
  int TremKnob = mozziAnalogRead(TREM_PIN); // value is 0-1023
  //We use a running average filter to smooth the sensor input
  TremValue =alpha * TremKnob + (1. - alpha) * TremValue;
  Q24n8 TremFreq=float_to_Q24n8((float)map(TremValue,0,1023,1,301)/10.);
  aTremolo.setFreq_Q24n8(TremFreq);
  
  int TremDepKnob=mozziAnalogRead(TREMDEP_PIN);
  //We use a running average filter to smooth the sensor input
  TremDepValue =alpha * TremDepKnob + (1. - alpha) * TremDepValue;
  TremoloDepth = byte(map(TremDepValue,0,1023,0,255));
  
  int VibKnob = mozziAnalogRead(VIB_PIN); // value is 0-1023
  //We use a running average filter to smooth the sensor input
  VibValue =alpha * VibKnob + (1. - alpha) * VibValue;
  Q24n8 VibFreq=float_to_Q24n8((float)map(VibValue,0,1023,1,301)/10.);
  //Serial.println((float)map(VibValue,0,1023,1,610)/20.);
  aVibrato.setFreq_Q24n8(VibFreq);

  int VibDepKnob=mozziAnalogRead(VIBDEP_PIN);
  //We use a running average filter to smooth the sensor input
  VibDepValue =alpha * VibDepKnob + (1. - alpha) * VibDepValue;
  VibratoDepth = byte(map(VibDepValue,0,1023,0,255));

  int FilterKnob=mozziAnalogRead(FILTER_PIN);
  //We use a running average filter to smooth the sensor input
  CutOffValue =int(alpha * FilterKnob + (1. - alpha) * CutOffValue);
  svf.setCentreFreq(map(CutOffValue,0,1023,50,4000));

}

int updateAudio(){
      Q15n16 vibrato = (Q15n16)VibratoDepth * aVibrato.next();
      int Tremolo=255u-(((128u+aTremolo.next())*TremoloDepth)>>8);
      int Osc=(aOscil.phMod(vibrato) * Tremolo) >> 8;// return an int signal centred around 0
      int Out=int(svf.next(Osc)*0.9); // Apply State Variable filtering
      return Out;
}

void loop(){
  audioHook(); // required here
}

Qualche altro esempio

Per qualsiasi problema, curiosità e suggerimento non esitare a scriverci.

Codice di sicurezza:
security code
Inserire un codice di sicurezza.:

Invia

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *