
Bluetooth Enabled Keyboard/Synthesizer for mbed
Dependencies: mbed 4DGL-uLCD-SE SDFileSystem mbed-rtos
Diff: main.cpp
- 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");