Non ci sono prodotti a carrello.
A questo punto con l’istruzione riportata di seguito creeremo un oscillatore sinusoidale:
Oscil <2048, AUDIO_RATE> aSin(SIN2048_DATA);
Un valore che importante è il CONTROL_RATE. Esso ha un valore predefinito di 64, ma si può cambiare se si desidera controllare gli aggiornamenti più spesso. Anche in questo caso deve essere un numero potenza di due per permettere a Mozzi di ottimizzare i calcoli e di conseguenza la velocità di esecuzione.
#define CONTROL_RATE 128
Il valore và inserito come parametro in startMozzi() che si trova in setup ():
startMozzi(CONTROL_RATE);
Esso imposta un timer per chiamare updateControl () alla frequenza impostata.
La frequenza dell’oscillatore appena creato può essere impostata in numerosi modi , in questo caso la imposteremo a 440Hz.:
aSin.setFreq(440);
Ora il setup () diventa:
void setup(){ startMozzi(CONTROL_RATE); aSin.setFreq(440); }
Le prossime funzioni necessarie da inserire sono updateControl () e updateAudio ().
In questo esempio, la frequenza è già stata impostata e l’oscillatore ha solo bisogno di essere eseguito in updateAudio () , utilizzando il aSin.next().
void updateControl(){ // no controls being changed } int updateAudio(){ return aSin.next(); }
Come ultima funzione inseriremo audioHook () in loop () .
void loop(){ audioHook(); }
Mediante questa funzione la generazione del suono viene effettivamente sintetizzata, in base ai parametri impostati in precedenza. Il buffer di uscita che viene costantemente riempito e svuotato alla frequenza audio di Mozzi. Per questo motivo, di solito è meglio di evitare di mettere qualsiasi altro codice in loop () . E ‘importante per la progettazione di uno programma efficiente inserire i calcoli lenti in updateControl () e setup () . Mentre è meglio mantenere updateAudio () con meno codice possibile.
Ecco l’intero Programma:
#include <MozziGuts.h> #include <Oscil.h> #include <tables/sin2048_int8.h> #define CONTROL_RATE 128 Oscil <2048, AUDIO_RATE> aSin(SIN2048_DATA); void setup(){ aSin.setFreq(440); startMozzi(CONTROL_RATE); } void updateControl(){ } int updateAudio(){ return aSin.next(); } void loop(){ audioHook(); }
Aggiunta di un segnale: controllo vibrato
Il Vibrato può essere aggiunto al programma cambiando periodicamente la frequenza dell’onda audio con un oscillatore a bassa frequenza. Il nuovo controllo utilizzerà i medesimi parametri prima impostati. Per convenzione utilizzeremo come lettera iniziale del controllo ‘k’.
Oscil <2048, CONTROL_RATE> kVib(SIN2048_DATA);
Questa volta la frequenza può essere impostata con un valore in virgola mobile:
kVib.setFreq(6.5f);
Ora l’oscillatore ddel vibrato può modulare la frequenza dell’oscillatore audio mediante KVib.next () inserita in updateControl ().
void updateControl(){ float vibrato = depth * kVib.next(); aSin.setFreq(centre_freq+vibrato); }
Ecco ul programma del vibrato:
#include <MozziGuts.h> #include <Oscil.h> #include <tables/sin2048_int8.h> #define CONTROL_RATE 128 Oscil <2048, AUDIO_RATE> aSin(SIN2048_DATA); Oscil <2048, CONTROL_RATE> kVib(SIN2048_DATA); float centre_freq = 440.0; float depth = 0.25; void setup(){ kVib.setFreq(6.5f); startMozzi(CONTROL_RATE); } void updateControl(){ float vibrato = depth * kVib.next(); aSin.setFreq(centre_freq+vibrato); } int updateAudio(){ return aSin.next(); } void loop(){ audioHook(); }
Il nostro progetto:
A questo punto abbiamo le basi per realizzare qualcosa di nostro da far vedere con orgoglio ad amici e parenti dicendo ‘Questo l’ho fatto io’. Una premessa hardware riguardo Fishino e Mozzi… l’uscita audio si trova sul pin 9 . Per cui se si vuole collegare una cuffia per ascoltare il suono generato la stessa và collegata al pin 9 come più ad a gnd come massa. Vediamo il codice completo del programma che gira sotto Fishino che poi andremo ad analizzare passo, passo in particolare per la parte che riguarda il protocollo.
#include <MozziGuts.h> #include <Oscil.h> // oscillator #include <tables/cos2048_int8.h> // table suoni x Oscils #include <Smooth.h> #include <AutoMap.h> // maps input imprevisti riguardo il range #define CONTROL_RATE 256 const byte numChars = 32; char receivedChars[numChars]; String receivedCharsS; boolean newData = false; /********************************************** * definizzione variabili dei comandi * di ingresso dalla seriale */ int freqVal; int knob2; int knob_value; int LDR1_value; int LDR2_value; // minima e massima frequnza della portante const int MIN_CARRIER_FREQ = 22; const int MAX_CARRIER_FREQ = 440; const int MIN = 1; const int MAX = 10; const int MIN_2 = 1; const int MAX_2 = 15; // Intensità desiderata max e min, per AutoMap, si noti che a causa della dinamica inversa sono invertiti const int MIN_INTENSITY = 700; const int MAX_INTENSITY = 10; // velocità minima e massima per AutoMap, si noti che a causa della dinamica inversa sono invertiti const int MIN_MOD_SPEED = 10000; const int MAX_MOD_SPEED = 1; AutoMap kMapCarrierFreq(0, 1023, MIN_CARRIER_FREQ, MAX_CARRIER_FREQ); AutoMap kMapIntensity(0, 1023, MIN_INTENSITY, MAX_INTENSITY); AutoMap kMapModSpeed(0, 1023, MIN_MOD_SPEED, MAX_MOD_SPEED); AutoMap mapThis(0, 1023, MIN, MAX); AutoMap mapThisToo(0, 1023, MIN_2, MAX_2); Oscil<COS2048_NUM_CELLS, AUDIO_RATE> aCarrier(COS2048_DATA); Oscil<COS2048_NUM_CELLS, AUDIO_RATE> aModulator(COS2048_DATA); Oscil<COS2048_NUM_CELLS, CONTROL_RATE> kIntensityMod(COS2048_DATA); int mod_ratio = 5; // limpidezza (armoniche) long fm_intensity; // variabile x intensità da updateControl a updateAudio // per fulizia della gnerazione del suono float smoothness = 0.95f; Smooth <long> aSmoothIntensity(smoothness); void setup() { Serial.begin(115200); // set up Seriale startMozzi(CONTROL_RATE); } void updateControl() { recvWithStartEndMarkers(); showNewData(); /*********************************** ricezione comandi da vb.net ***********************************/ int Test = receivedCharsS.indexOf("LDR3"); if (Test >= 0) { Serial.print("CMD 1 "+receivedCharsS+"\n"); int TestV = receivedCharsS.indexOf(":"); if (TestV >= 0) { Serial.print("CMD 2 "+receivedCharsS+"\n"); String Valore = receivedCharsS.substring(TestV + 1, receivedCharsS.length()); int Val = Valore.toInt(); freqVal = Val; Serial.print("CMD 3 "+receivedCharsS+"\n"); } } int Test2 = receivedCharsS.indexOf("LDR4"); if (Test2 >= 0) { Serial.print("CMD 1 "+receivedCharsS+"\n"); int TestV = receivedCharsS.indexOf(":"); if (TestV >= 0) { Serial.print("CMD 2 "+receivedCharsS+"\n"); String Valore = receivedCharsS.substring(TestV + 1, receivedCharsS.length()); int Val = Valore.toInt(); knob2 = Val; Serial.print("CMD 3 "+receivedCharsS+"\n"); } } int Test3 = receivedCharsS.indexOf("KNOB"); if (Test3 >= 0) { Serial.print("CMD 1 "+receivedCharsS+"\n"); int TestV = receivedCharsS.indexOf(":"); if (TestV >= 0) { Serial.print("CMD 2 "+receivedCharsS+"\n"); String Valore = receivedCharsS.substring(TestV + 1, receivedCharsS.length()); int Val = Valore.toInt(); knob_value = Val; Serial.print("CMD 3 "+receivedCharsS+"\n"); } } int FRQ = mapThis(freqVal); int knob2Val = mapThis(knob2); // map la varabile knob_value sulla portante della frequenza //------------------------------------------------------- int carrier_freq = kMapCarrierFreq(knob_value); //Calcola il rapporto della frequenza di modulazione //------------------------------------------------- int mod_freq = carrier_freq * mod_ratio * FRQ; // setta la frequenza dell'oscillatore FM //------------------------------------------------ aCarrier.setFreq(carrier_freq); aModulator.setFreq(mod_freq); int Test4 = receivedCharsS.indexOf("LDR1"); if (Test4 >= 0) { Serial.print("CMD 1 "+receivedCharsS+"\n"); int TestV = receivedCharsS.indexOf(":"); if (TestV >= 0) { Serial.print("CMD 2 "+receivedCharsS+"\n"); String Valore = receivedCharsS.substring(TestV + 1, receivedCharsS.length()); int Val = Valore.toInt(); LDR1_value = Val; Serial.print("CMD 3 "+receivedCharsS+"\n"); } } int LDR1_calibrated = kMapIntensity(LDR1_value); // calculate the fm_intensity fm_intensity = ((long)LDR1_calibrated * knob2Val * (kIntensityMod.next() + 128)) >> 8; //lo shift >> 8 equivale ad una moltiplicazione a 8 bit int Test5 = receivedCharsS.indexOf("LDR2"); if (Test5 >= 0) { Serial.print("CMD 1 "+receivedCharsS+"\n"); int TestV = receivedCharsS.indexOf(":"); if (TestV >= 0) { Serial.print("CMD 2 "+receivedCharsS+"\n"); String Valore = receivedCharsS.substring(TestV + 1, receivedCharsS.length()); int Val = Valore.toInt(); LDR2_value = Val; Serial.print("CMD 3 "+receivedCharsS+"\n"); } } // usa una variabile float per le basse frequenze float mod_speed = (float)kMapModSpeed(LDR2_value) / 1000; kIntensityMod.setFreq(mod_speed); } int updateAudio() { long modulation = aSmoothIntensity.next(fm_intensity) * aModulator.next(); return aCarrier.phMod(modulation); } void loop() { audioHook(); } void recvWithStartEndMarkers() { static boolean recvInProgress = false; static byte ndx = 0; char startMarker = '<'; char endMarker = '>'; char rc; receivedCharsS = ""; // if (Serial.available() > 0) { while (Serial.available() > 0 && newData == false) { rc = Serial.read(); if (recvInProgress == true) { if (rc != endMarker) { receivedChars[ndx] = rc; receivedCharsS += rc; ndx++; if (ndx >= numChars) { ndx = numChars - 1; } } else { receivedChars[ndx] = '\0'; // terminate the string recvInProgress = false; ndx = 0; newData = true; } } else if (rc == startMarker) { recvInProgress = true; } } } void showNewData() { if (newData == true) { Serial.print("This just in ... "); Serial.print(receivedCharsS+"-"); Serial.println(receivedChars); newData = false; } }
3 Commenti