Bluetooth Enabled Keyboard/Synthesizer for mbed

Dependencies:   mbed 4DGL-uLCD-SE SDFileSystem mbed-rtos

Revision:
24:3bd4e691ae59
Parent:
23:cf9d43d5a5b4
Child:
25:5a312725710a
--- a/main.cpp	Sat Apr 30 23:01:52 2016 +0000
+++ b/main.cpp	Sun May 01 00:25:02 2016 +0000
@@ -22,17 +22,18 @@
 volatile char keyPress;
 WaveType myWave = sine; // default to sine wave
 volatile int currentOctave = 4; // default to 4 because thats where middle C is
-volatile int currentAttackVal = 3;   // values will range from 1-5, default to 3
-volatile int currentDecayVal = 3;    // values will range from 1-5, default to 3
-volatile int currentSustainVal = 3;  // values will range from 1-5, default to 3
-volatile int currentReleaseVal = 3;  // values will range from 1-5, default to 3
-float currentAttackTable[4] = {0 , 0.63 , 0.84 , 1};             // pointer to the correct attack coefficient table
-float currentDecayTable[4] = {0.77 , 0.7 , 0.63 , 0.60};             // pointer to the correct decay coefficient table
-float currentSustainTable[20]= {0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6};           // pointer to the correct sustain coefficient table
-float currentReleaseTable[4] = {0.33 , 0.16 , 0.08 , 0};           // pointer to the correct release coefficient table
-short unsigned Analog_out_data[32];
-float coefficientMatrix[32];       // Array to hold all 32 coefficients for modulating the amplitude of the waveform
+int currentADSR = 3;                    // value representing which envelope shape is currently selected. default is 3
+float attackVals[32] = {};             // array that holds the attack coefficients
+float decayVals[32] = {};             // array that holds the decay coefficients
+float sustainVals[32]= {};           // array that holds the sustain coefficients
+float releaseVals[32] = {};           // array that holds the release coefficients
+short unsigned Analog_out_data[32]; // holds the samples that will be output to p18
 volatile int noteFreq;              // the current frequency of the note being played
+float noteDuration = 2.0f;          // default note duration will be 2 seconds
+float attackPercentage[5] = {};     // holds values for percentage of waveform that the attack should take up
+float decayPercentage[5] = {};      // holds values for percentage of waveform that the decay should take up
+float sustainPercentage[5] = {};    // holds values for the percentage of waveform that the sustain should take up
+float releasePercentage[5] = {};    // holds values for the percentage of waveform that the sutain should take up
 
 /* Coefficient Matrices Corresponding to Different Attack Values
 each matrix is comprised of 4 elements (32/8). The first matrix corresponds
@@ -122,135 +123,38 @@
     noteFreq = frequency;
 }
 
-void change_Attack_Table(int attackVal)     // change which table of coefficients to use for altering the attack portion of the waveform
+/* Generates the coefficients that will shape the waveform */
+
+void initialize_ADSRVals()
 {
-    for(int i = 0; i < 4; i++){
-        if( attackVal == 5){
-            currentAttackTable[i] = attackVals5[i];
-        }
-        else if( attackVal == 4){
-            currentAttackTable[i] = attackVals4[i];
-        }
-        else if( attackVal == 3){
-            currentAttackTable[i] = attackVals3[i];
-        }
-        else if( attackVal == 2){
-            currentAttackTable[i] = attackVals2[i];
-        }
-        else if( attackVal == 1){
-            currentAttackTable[i] = attackVals1[i];
-        }
-    }
-}
-
-void change_Decay_Table(int decayVal)       // change which table of coefficients to use for altering the decay portion of the waveform
-{
-    for(int i = 0; i < 4; i++){
-        if( decayVal == 5){
-            currentDecayTable[i] = decayVals5[i];
-        }
-        else if( decayVal == 4){
-            currentDecayTable[i] = decayVals4[i];
-        }
-        else if( decayVal == 3){
-            currentDecayTable[i] = decayVals3[i];
-        }
-        else if( decayVal == 2){
-            currentDecayTable[i] = decayVals2[i];
-        }
-        else if( decayVal == 1){
-            currentDecayTable[i] = decayVals1[i];
-        }
+    for(int j = 0; j < 32; j++)
+    {
+        attackVals[j] = (float)j/32.0f;
+        decayVals[j] = 1.0f - (j*((1-sustainAmplitude)/32))
+        sustainVals[j] = (float)sustainAmplitude;
+        releaseVals[j] = (float)sustainAmplitude - (((sustainAmplitude)/32)*j);
     }
 }
 
-    void change_Sustain_Table(int sustainVal)   // change which table of coefficients to use for altering the sustain portion of the waveform
-{
-  
-    for(int i = 0; i < 20; i++){
-        if( sustainVal == 5){
-            currentSustainTable[i] = sustainVals5[i];
-        }
-        else if( sustainVal == 4){
-            currentSustainTable[i] = sustainVals4[i];
-        }
-        else if( sustainVal == 3){
-            currentSustainTable[i] = sustainVals3[i];
-        }
-        else if( sustainVal == 2){
-            currentSustainTable[i] = sustainVals2[i];
-        }
-        else if( sustainVal == 1){
-            currentSustainTable[i] = sustainVals1[i];
-        }
-    }
-}
+/* Generates the durations of each part of the waveform (attack,decay,sustain, and release)*/
 
-void change_Release_Table(int releaseVal)       // change which table of coefficients to use for altering the release portion of the waveform
+void generate_durations(int index)
 {
-     for(int i = 0; i < 4; i++){
-        if( releaseVal == 5){
-            currentReleaseTable[i] = releaseVals5[i];
-        }
-        else if( releaseVal == 4){
-            currentReleaseTable[i] = releaseVals4[i];
-        }
-        else if( releaseVal == 3){
-            currentReleaseTable[i] = releaseVals3[i];
-        }
-        else if( releaseVal == 2){
-            currentReleaseTable[i] = releaseVals2[i];
-        }
-        else if( releaseVal == 1){
-            currentReleaseTable[i] = releaseVals1[i];
-        }
-    }
-} 
+        attackDuration = attackPercentage[index-1] * noteDuration;
+        decayDuration = decayPercentage[index-1] * noteDuration;
+        sustainDuration = sustainPercentage[index-1] * noteDuration;
+        releaseDuration = releasePercentage[index-1] * noteDuration;
+}
+        
 
-/* Having different sustain values for the amplitude of the wave would make the math neccesary to generate the other
-coefficient matrices very complex, so only .6 is used, meaning a sustain value of 1-5 will all correspond to a sustain amplitude
-of .6. Since the sustain coefficient matrices are 20 elements long, they are all filled in a for loop with this function call.
-*/
 
-void initialize_sustainVals()   
-{
-    for(int j = 0; j < 20; j++)
-    {
-        sustainVals5[j] = .6;
-        sustainVals4[j] = .6;
-        sustainVals3[j] = .6;
-        sustainVals2[j] = .6;
-        sustainVals1[j] = .6;
-    }
-}
 /* Applies the envelope to the waveform. Each set of coefficients is applied to a certain portion of the waveform to alter its shape.
 The attack coefficients are appplied to the first 4 samples, the decay coefficients are applied to samples 5-8, the sustain coefficients
 are applied to samples 9 - 28, and the release coefficients are appplied to samples 29-32.
 */
 
 
-void apply_Envelope(void){                                          
-    for(int j = 0; j < 32 ; j++)
-    {
-        if( j < 4 ){
-            coefficientMatrix[j] = currentAttackTable[j];
-            //PC.printf("%f\n\r", currentAttackTable[j]);
-        }
-        else if(( j < 8) && ( j > 3)){
-            coefficientMatrix[j] = currentDecayTable[j-4];
-            //PC.printf("%f\n\r", currentDecayTable[j-4]);
-        }
-        else if(( j < 28) && (j > 7)){
-            coefficientMatrix[j] = currentSustainTable[j-8];
-            //PC.printf("%f\n\r", currentSustainTable[j-8]);
-        }
-        else if(( j < 32) && (j > 27)){
-            coefficientMatrix[j] = currentReleaseTable[j-28];
-            //PC.printf("%f\n\r", currentReleaseTable[j-28]);
-        }
-        PC.printf("%f\n\r", coefficientMatrix[j]);
-    }
-}
+
 
 void generate_sineWave(int frequency)       // Generates samples for a sine wave of a given input frequency
 {
@@ -295,17 +199,17 @@
         case sine:
             //Generate sine wave values
             generate_sineWave(frequency);
-            apply_Envelope();
+            generate_durations(currentASDR);
             break;
         case square:
             //Generate square wave values
             generate_squareWave(frequency);
-            apply_Envelope();
+            generate_durations(currentASDR);
             break;
         case sawtooth:
             //Generate sawtooth wave values
             generate_sawtoothWave(frequency);
-            apply_Envelope();
+            generate_durations(currentASDR);
             break;
         default:
         break;
@@ -390,6 +294,7 @@
     mkdir("/sd/noteRecords", 0777);             // make directory to hold the record of notes played
 
     initialize_sustainVals();                   // fill the lookup tables with the sustain values in them
+    initialize_ADSRVals();                      // fill the lookup tables for ADSR percentages
     
     PC.baud(9600);                              // setup baud rate for PC serial connection
     Blue.baud(9600);                            // setup baud rate for bluetooth serial connection
@@ -465,81 +370,31 @@
             printf("Cannot lower octave below 1.\r\n");
             readyFlag = false;
         }
-        else if((keyPress == RAISE_ATTACK_KEY) && (readyFlag)){ // button Q pressed
-            // Raise Attack Value
-            if(currentAttackVal < 5){
-            currentAttackVal++;
-            change_Attack_Table(currentAttackVal);
-            }
-            else
-            printf("Cannot raise value above 5.\r\n");
+        
+        else if((keyPress == RAISE_DURATION_KEY) && (readyFlag)){ // button E pressed
+            noteDuration++;
             readyFlag = false;
         }
-        else if((keyPress == LOWER_ATTACK_KEY) && (readyFlag)){ // button A pressed
-            // Lower Attack Value
-            if(currentAttackVal > 1){
-            currentAttackVal--;
-            change_Attack_Table(currentAttackVal);
-            }
+        else if((keyPress == LOWER_DURATION_KEY) && (readyFlag)){ // button D pressed
+            if(noteDuration >= 2)
+            noteDuration--;
             else
-            printf("Cannot lower value below 1.\r\n");
+            printf("Cannot decrease duration further.\n\r");
             readyFlag = false;
         }
-        else if((keyPress == RAISE_DELAY_KEY) && (readyFlag)){ // button W pressed
-            // Raise Delay Value
-            if(currentDecayVal < 5){
-            currentDecayVal++;
-            change_Decay_Table(currentDecayVal);
+        else if((keyPress == RAISE_ADSR_KEY) && (readyFlag)){ // button R pressed
+            // Raise Release Value
+            if(currentReleaseVal < 5){
+            currentADSR++;
             }
             else
             printf("Cannot raise value above 5.\r\n");
             readyFlag = false;
         }
-        else if((keyPress == LOWER_DELAY_KEY) && (readyFlag)){ // button S pressed
-            // Lower Delay Value
-            if(currentDecayVal > 1){
-            currentDecayVal--;
-            change_Decay_Table(currentDecayVal);
-            }
-            else
-            printf("Cannot lower value below 1.\r\n");
-            readyFlag = false;
-        }
-        else if((keyPress == RAISE_SUSTAIN_KEY) && (readyFlag)){ // button E pressed
-            // Raise Sustain Value
-            if(currentSustainVal < 5){
-            currentSustainVal++;
-            change_Sustain_Table(currentSustainVal);
-            }
-            else
-            printf("Cannot raise value above 5.\r\n");
-            readyFlag = false;
-        }
-        else if((keyPress == LOWER_SUSTAIN_KEY) && (readyFlag)){ // button D pressed
-            // Lower Sustain Value
-            if(currentSustainVal > 1){
-            currentSustainVal--;
-            change_Sustain_Table(currentSustainVal);
-            }
-            else
-            printf("Cannot lower value below 1.\r\n");
-            readyFlag = false;
-        }
-        else if((keyPress == RAISE_RELEASE_KEY) && (readyFlag)){ // button R pressed
-            // Raise Release Value
-            if(currentReleaseVal < 5){
-            currentReleaseVal++;
-            change_Release_Table(currentReleaseVal);
-            }
-            else
-            printf("Cannot raise value above 5.\r\n");
-            readyFlag = false;
-        }
-        else if((keyPress == LOWER_RELEASE_KEY) && (readyFlag)){ // button F pressed
+        else if((keyPress == LOWER_ADSR_KEY) && (readyFlag)){ // button F pressed
             // Lower Release Value
             if(currentReleaseVal > 1){
-            currentReleaseVal--;
-            change_Release_Table(currentReleaseVal);
+            currentADSR--;
             }
             else
             printf("Cannot lower value below 1.\r\n");