Sound Generation

Dependencies:   mbed

Fork of Nucleo-DAC-Algorithm by Giuseppe Falagario

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Sound-Generation.cpp Source File

Sound-Generation.cpp

00001 // Tested : NUCLEO F207ZG
00002 #include "mbed.h"
00003 
00004 // Definizione periferiche
00005 Serial pc(USBTX, USBRX);
00006 AnalogOut OutWave(PA_5);
00007 //DigitalOut DigitalWave(PA_5);
00008 DigitalOut led1(LED1);
00009 DigitalOut led2(LED2);
00010 DigitalOut led3(LED3);
00011 
00012 // definizione della frequenza delle note ottava centrale del pianoforte
00013 #define C 261.63
00014 #define Cd 277.18
00015 #define Db 277.18
00016 #define D 293.66
00017 #define Dd 311.13
00018 #define Eb 311.13
00019 #define E 329.63
00020 #define F 349.23
00021 #define Fd 369.99
00022 #define Gb 369.99
00023 #define G 392.9
00024 #define Gd 415.3
00025 #define Ab 415.3
00026 #define A 440.0
00027 #define Ad 466.16
00028 #define Bb 466.16
00029 #define B 493.18
00030 
00031 
00032 
00033 
00034 
00035 
00036 // numero di campioni che compongono un periodo della sinusoide in Output sull'ADC
00037 #define SAMPLESINENUM   45// consigliabile avere  multipli di 45
00038 
00039 // parametri dell'onda coseno da generare
00040 #define PI        (3.141592653589793238462)
00041 #define AMPLITUDE 32767 //(1.0)    // x * 3.3V
00042 #define PHASE     (PI/2) // 2*pi è un periodo
00043 #define OFFSET    32767 //(0x7FFF)
00044 
00045 // numero di note componenti la scala diatonica
00046 #define NUMTONE 120
00047 
00048 // Output LED di diagnostica
00049 DigitalOut led(LED1);
00050 
00051 // ticker per la generazione dell'onda con DAC
00052 Ticker SampleOutTicker;
00053 
00054 // Buffer contenente la sinusoide da porre in output.
00055 unsigned short usaSine[SAMPLESINENUM];
00056 
00057 // prototipo di funzione che genera i campioni della sinusoide da utilizzare per la generazione tramite DAC
00058 void CalculateSinewave(void);
00059 
00060 // carattere in arrivo dal PC
00061 volatile char cReadChar;
00062  
00063 // indice, nell'array, del campione da porre in output
00064 volatile int nSampleOutIndex;
00065 // contatore dei campioni in output sul DAC
00066 volatile int nSampleOutCount;
00067 // Periodo di generazione campioni in output DeltaT = T/NumSample
00068 double fDeltaT;
00069 // amplificazione per il dato da spedire sull'ADC
00070 volatile double fAmp;
00071 //volatile double fAmpNew;
00072 // flag per bloccare la generazione del segnale
00073 volatile bool bStop;
00074 // frequenza segnale da generare
00075 volatile double fFreq;
00076 // periodo della sinusoide da generare
00077 double fPeriod;
00078 double dDiatonic[NUMTONE];
00079 
00080 //****************************
00081 // Create the sinewave buffer
00082 //****************************
00083 void CalculateSinewave(int nOffset, int nAmplitude, double fPhase)
00084 {
00085     // variabile contenente l'angolo in radianti
00086     double fRads;
00087     // indici per i cicli
00088     int nIndex;
00089     // passo in frequenza fissato dal numero di campioni in cui voglio dividere un periodo di sinusoide: DeltaF = 360°/NUMSAMPLE
00090     double fDeltaF;
00091     // angolo per il quale bisogna calcolare il valore di sinusoide: fAngle = nIndex*DeltaF
00092     double fAngle;
00093     
00094     fDeltaF = 360.0/SAMPLESINENUM;
00095     for (nIndex = 0; nIndex < SAMPLESINENUM; nIndex++) 
00096     {
00097         fAngle = nIndex*fDeltaF; // angolo per il quale bisogna calcolare il campione di sinusoide
00098         fRads = (PI * fAngle)/180.0; // Convert degree in radian
00099         //usaSine[nIndex] = AMPLITUDE * cos(fRads + PHASE) + OFFSET;
00100         usaSine[nIndex] = nAmplitude * cos(fRads + fPhase) + nOffset;
00101     }
00102 }
00103 
00104 
00105 //**********************************************
00106 // Crea le frequenze delle note del pianoforte
00107 //**********************************************
00108 void CreateDiatonic()
00109 {
00110     int nTono;
00111     int nOttava;
00112     
00113     // ottava centrale = ottava 4
00114     dDiatonic[4*12+0]=261.63;   // C
00115     dDiatonic[4*12+1]=277.18;   // C#/Db
00116     dDiatonic[4*12+2]=293.66;   // D
00117     dDiatonic[4*12+3]=311.13;   // D#/Eb
00118     dDiatonic[4*12+4]=329.63;   // E
00119     dDiatonic[4*12+5]=349.23;   // F
00120     dDiatonic[4*12+6]=369.99;   // F#/Gb
00121     dDiatonic[4*12+7]=392.00;   // G
00122     dDiatonic[4*12+8]=415.30;   // G#/Ab
00123     dDiatonic[4*12+9]=440.00;   // A
00124     dDiatonic[4*12+10]=466.16;  // A#/Bb
00125     dDiatonic[4*12+11]=493.88;  // B
00126     
00127     // dalla ottava 5 alla 9
00128     for(nOttava=5; nOttava<9; nOttava++)
00129     {
00130         for(nTono=0; nTono<12; nTono++)
00131         {
00132             dDiatonic[(nOttava*12)+nTono]=dDiatonic[((nOttava-1)*12)+nTono]*2;
00133         }
00134     }
00135     
00136     // dalla ottava 0 alla 3
00137     for(nOttava=3; nOttava>=0; nOttava--)
00138     {
00139         for(nTono=0; nTono<12; nTono++)
00140         {
00141             dDiatonic[(nOttava*12)+nTono]=dDiatonic[((nOttava+1)*12)+nTono]/2;
00142         }
00143     }
00144 }
00145 
00146 //***************************
00147 // generazione sample da DAC
00148 //***************************
00149 void SampleOut() 
00150 {
00151     // se è stato inviato il comando Stop, non fare niente fino a nuovo comando
00152     if(bStop)
00153     {
00154     }
00155     else // se non è stato inviato il comando di bStop continua
00156     {
00157         // output del campione della forma d'onda
00158         OutWave.write_u16(usaSine[nSampleOutIndex]);
00159         
00160         // incrementa l'indice del campione in output, modulo NUMSAMPLE: se NUMSAMPLE è 360, nSampleOutIndex va da 0 a 359
00161         nSampleOutIndex++;
00162         if(nSampleOutIndex >= SAMPLESINENUM) 
00163         {
00164             nSampleOutIndex=0; 
00165         }
00166         
00167     }
00168 }
00169 
00170 
00171 
00172 
00173 //*******************
00174 // Loop Principale
00175 //*******************  
00176 int main()
00177 {
00178     // configura velocità della comunicazione seriale su USB-VirtualCom e invia messaggio di benvenuto
00179     pc.baud(921600); //921600 bps
00180     
00181     
00182     // messaggio di benvenuto
00183     pc.printf("\r\nHallo Amaldi Students - Exercise 9 \r\n");
00184     pc.printf("\r\n*** SineWave Generation ***\r\n");
00185     
00186     //inizializza variabili
00187     cReadChar = 0;
00188     nSampleOutIndex=0;
00189     nSampleOutCount=0;
00190     bStop=true;
00191     
00192     // test dei LED
00193     led1=1; //Verde
00194     wait_ms(1000);
00195     led1=0;
00196     led2=1; // Blu
00197     wait_ms(1000);
00198     led2=0;
00199     led3=1; //Rosso
00200     wait_ms(1000);
00201     led3=0;
00202     
00203     
00204     while(true)
00205     {     
00206         // verifica se è arrivato un carattere dalla seriale del pc
00207         if(pc.readable())
00208         {
00209             cReadChar = pc.getc(); // Read hyperterminal  
00210              
00211              // genera la nota corrispondente al carattere ricevuto
00212             switch(cReadChar)
00213             {
00214                 //DO
00215                 case 'c':
00216                 case 'C':
00217                 {
00218                     fFreq=261.63;// frequenza della sinusoide DO da generare
00219                     pc.printf("\n\r--- Generazione DO = %.2f Hz ampiezza nominale ---\n\r", fFreq);
00220                     bStop = false;
00221                 } break;
00222                 // RE
00223                 case 'd':
00224                 case 'D':
00225                 {
00226                     fFreq=293.66;// frequenza della sinusoide RE da generare
00227                     pc.printf("\n\r--- Generazione RE = %.2f Hz ampiezza nominale ---\n\r", fFreq);
00228                     bStop = false;
00229                 } break;
00230                 // RE#/MIb
00231                 case 'm':
00232                 case 'M':
00233                 {
00234                     fFreq=311.13;
00235                     pc.printf("\n\r--- Generazione Mib = %.2f Hz ampiezza nominale ---\n\r", fFreq);
00236                     bStop = false;
00237                 } break;
00238                 case 'e':
00239                 case 'E':
00240                 {
00241                     fFreq=329.63; // frequenza della sinusoide MI da generare
00242                     pc.printf("\n\r--- Generazione MI = %.2f Hz ampiezza nominale ---\n\r", fFreq);
00243                     bStop = false;
00244                 } break;
00245                 case 'f':
00246                 case 'F':
00247                 {
00248                     fFreq=349.23;// frequenza della sinusoide FA da generare
00249                     pc.printf("\n\r--- Generazione FA = %.2f Hz ampiezza nominale ---\n\r", fFreq);
00250                     bStop = false;
00251                 } break;
00252                 
00253                 // SOL
00254                 case 'g':
00255                 case 'G':
00256                 {
00257                     fFreq=392.0;
00258                     pc.printf("\n\r--- Generazione SOL = %.2f Hz ampiezza nominale ---\n\r", fFreq);
00259                     bStop = false;
00260                 } break;
00261                 // LA
00262                 case 'a':
00263                 case 'A':
00264                 {
00265                     fFreq=440.0; // frequenza della sinusoide LA da generare
00266                     pc.printf("\n\r--- Generazione LA = %.2f Hz ampiezza nominale ---\n\r", fFreq);
00267                     bStop = false;
00268                 } break;
00269                 //SI
00270                 case 'b':
00271                 case 'B':
00272                 {
00273                     fFreq=493.88;// frequenza della sinusoide SI da generare
00274                     pc.printf("\n\r--- Generazione SI = %.2f Hz ampiezza nominale ---\n\r", fFreq);
00275                     bStop = false;
00276                 } break;
00277                 
00278                 // pausa
00279                 case ' ':
00280                 {
00281                     bStop=true;
00282                     pc.printf("\n\r--- Generation Stopped ---\n\r");
00283                 } break;
00284                 default:
00285                 {
00286                     bStop=true; // se la nota non è riconosciuta blocca la generazione
00287                     pc.printf("\n\r--- Wrong Tone ---\n\r");
00288                 } break;  
00289             } // switch (cReadChar)
00290             
00291             // genera la frequenza relativa alla nota che è stata selezionata
00292             fAmp = 0.1; // coefficiente per il quale viene moltiplicato l'ampiezza massima
00293             fDeltaT = 1.0/(fFreq*SAMPLESINENUM);
00294             CalculateSinewave(32767, (32767*fAmp), (PI/2.0)); // generazione della sinusoide con valori nominali
00295             SampleOutTicker.attach(&SampleOut,fDeltaT); // avvia output della sinusoide per generazione
00296              
00297             
00298         }
00299         else // se non è stato premuto nessun tasto
00300         {
00301            
00302         } 
00303      }   
00304  
00305     /******* START ONDA DIGITALE FUNZIONA *****
00306     led1=1;
00307     led2=1;
00308     led3=1;
00309     while(true)
00310     {
00311         DigitalWave=0;
00312         //wait_us(2024); //SI
00313         //wait_us(2551); //SOL
00314         wait_us(1515); //MI
00315         DigitalWave=1;
00316         wait_us(1515);   
00317     }
00318     ****** END ONDA DIGITALE FUNZIONA ******/
00319 }