Austin Suszek / Mbed 2 deprecated MIDISynthesizer

Dependencies:   mbed USBDevice PinDetect

Files at this revision

API Documentation at this revision

Comitter:
asuszek
Date:
Wed Apr 13 19:46:28 2016 +0000
Parent:
7:8f270e2071e2
Child:
10:b9e14412cc23
Commit message:
Moved Audio into it's own folder

Changed in this revision

Audio/AudioEngine.cpp Show annotated file Show diff for this revision Revisions of this file
Audio/AudioEngine.h Show annotated file Show diff for this revision Revisions of this file
Audio/Synthesizer.cpp Show annotated file Show diff for this revision Revisions of this file
Audio/Synthesizer.h Show annotated file Show diff for this revision Revisions of this file
AudioEngine.cpp Show diff for this revision Revisions of this file
AudioEngine.h Show diff for this revision Revisions of this file
Synthesizer.cpp Show diff for this revision Revisions of this file
Synthesizer.h Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Audio/AudioEngine.cpp	Wed Apr 13 19:46:28 2016 +0000
@@ -0,0 +1,91 @@
+/* 
+ * The interface for all audio input and output.
+ * This class acts as a container for individual voices.
+ * It takes in MIDI events and handles processing and output.
+ *
+ * @author Austin Suszek
+ */
+ 
+#include "AudioEngine.h"
+
+#if USE_PWM
+PwmOut audioOut(p21);
+#else
+AnalogOut audioOut(p18);
+#endif
+ 
+AudioEngine::AudioEngine() {
+    // Initialize the synthesizers.
+    for (int i = 0; i < C::MAX_POLYPHONY; i++) {
+        synthesizers[i] = Synthesizer();   
+    }
+    
+    #if USE_PWM
+    audioOut.period(1.0/200000.0);
+    #endif
+    
+    // Set up the sampler.
+    samplePeriod.attach(this, &AudioEngine::outputAudio, 1.0 / float(C::SAMPLE_RATE));
+}
+
+void AudioEngine::midiNoteOn(const int key, const int velocity) {
+    // Find the firt disabled voice or the one that has been playing longest.
+    int64_t min  = synthesizers[0].getVoiceIndex();
+    int minIndex = 0;
+    for (int i = 1; i < C::MAX_POLYPHONY; i++) {
+        int64_t voiceIndex = synthesizers[i].getVoiceIndex();
+        if (voiceIndex < min) {
+            min = voiceIndex;
+            minIndex = i;
+        }   
+    }
+    
+    // Send the note to the minimum voice.
+    synthesizers[minIndex].midiNoteOn(key, velocity);
+}
+
+void AudioEngine::midiNoteOff(const int key) {
+    for (int i = 0; i < C::MAX_POLYPHONY; i++) {
+        if (synthesizers[i].isPlaying() && synthesizers[i].getCurrentKey() == key) {
+            synthesizers[i].midiNoteOff();
+            break;
+        }
+    }
+}
+
+void AudioEngine::nextSynth(int direction) {
+    // Hand the command down to the synthesizers.
+    for (int i = 0; i < C::MAX_POLYPHONY; i++) {
+        synthesizers[i].nextSynth(direction);   
+    }
+}
+
+void AudioEngine::outputAudio() {
+    float output = 0.0;
+    
+    // Poll all of the synthesizers.
+    for (int i = 0; i < C::MAX_POLYPHONY; i++) {
+        if (synthesizers[i].isPlaying()) {
+            output += synthesizers[i].getSample();   
+        } 
+    }
+    
+    // Scale the output by the number of voices.
+    output /= float(C::MAX_POLYPHONY);
+    // Check that we do not clip.
+    if (output > 1.0) {
+        output = 1.0;
+    }
+    if (output < -1.0) {
+        output = -1.0;
+    }
+    // Map [-1, 1] range to [0, 1] range.
+    audioOut = (output + 1.0) / 2.0;
+    
+    // Go back and process the next sample on all voices.
+    for (int i = 0; i < C::MAX_POLYPHONY; i++) {
+        if (synthesizers[i].isPlaying()) {
+            synthesizers[i].processBuffer();   
+        } 
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Audio/AudioEngine.h	Wed Apr 13 19:46:28 2016 +0000
@@ -0,0 +1,55 @@
+/**
+ * The interface for all audio input and output.
+ * This class acts as a container for individual voices.
+ * It takes in MIDI events and handles processing and output.
+ *
+ * @author Austin Suszek
+ */
+
+#ifndef AS_AUDIO_ENGINE_H
+#define AS_AUDIO_ENGINE_H
+
+#include "../Constants.h"
+#include "../mbed.h"
+#include "Synthesizer.h"
+
+class AudioEngine {
+public:
+
+    /**
+     * Constructor
+     */
+    AudioEngine();
+    
+    /**
+     * Signal the beginning of a note being pressed.
+     *
+     * @param key The integer representation of the note
+     * @param velocity (optional) The note velocity in the range of 0-127
+     */
+    void midiNoteOn(const int key, const int velocity = 0x7F);
+    
+    /**
+     * Signal the end of a note being pressed.
+     *
+     * @param key The integer representation of the note
+     */
+    void midiNoteOff(const int key);
+    
+    /**
+     * Switch to a new synth instrument.
+     *
+     * @param direction 1 for next, -1 for previous.
+     */
+    void nextSynth(int direction);
+    
+private:
+    
+    Ticker samplePeriod;
+    void outputAudio();
+    
+    Synthesizer synthesizers[C::MAX_POLYPHONY];
+    
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Audio/Synthesizer.cpp	Wed Apr 13 19:46:28 2016 +0000
@@ -0,0 +1,250 @@
+
+#include "Synthesizer.h"
+
+const float TWO_PI = 6.28318530717959;
+
+/**
+ * A function that acts as an individual synthesizer.
+ * It's job is to process the next sample at the current index
+ *   based on the current state of the overall synthesizer.
+ * Output should be in the range of [-1.0, 1.0] and saved back into the buffer.
+ */
+typedef void (Synthesizer::*processorFunction)();
+const int numSynths = 4;
+
+// Array of pointers to all synthesizer functions.
+processorFunction processors[] = {
+        &Synthesizer::processSine,
+        &Synthesizer::processTriangle,
+        &Synthesizer::processSquare,
+        &Synthesizer::processSaw,
+};
+
+int64_t Synthesizer::nextVoiceIndex = 0;
+
+Synthesizer::Synthesizer() {
+    bufferIndex = 0;
+    currentState = OFF;
+    nextBufferSize = -1;
+    voiceIndex = -1;
+    processorIndex = 0;
+}
+
+void Synthesizer::midiNoteOn(int key, int velocity) {
+    float freq = 440.0 * std::pow(2.0, float(key - 69) / 12.0);
+    
+    // Make sure we are in bounds.
+    if (freq < C::MIN_FREQUENCY) {
+        #ifdef DEBUG
+        printf("Error: Note is below minimum frequency");
+        #endif
+        return;   
+    }
+    
+    currentKey = key;
+    int size = int((float(C::SAMPLE_RATE) / freq) + 0.5);
+    
+    if (currentState == OFF) {
+        // We can immediately play the new note.
+        bufferSize = size;
+        this->velocity = float(velocity) / 127.0;
+        
+        voiceIndex = Synthesizer::nextVoiceIndex;
+        ++Synthesizer::nextVoiceIndex;
+        fromDisabled = true;
+        currentState = FILL;
+    } else {
+         // Put the values in the queue for later.
+         nextBufferSize = size;  
+         nextVelocity = float(velocity) / 127.0;
+    } 
+}
+
+void Synthesizer::midiNoteOff() {
+    // Begin release of current note.
+    currentState = RELEASE;
+    
+    // Clear the queue.
+    nextBufferSize = -1; 
+}
+
+float Synthesizer::getSample() {
+    if (currentState == FILL && fromDisabled) {
+        // The buffer may contain the release of the previous note so just return 0.0
+        return 0.0; 
+    }
+    
+    // Simply return the next sample. Do not increment.
+    return buffer[bufferIndex];   
+}
+
+void Synthesizer::processBuffer() {
+    // Assert that we are playing.
+    if (currentState == OFF) {
+        #ifdef DEBUG
+        printf("Error: Attempting to process a disabled synthesizer.");   
+        #endif
+        return;
+    }
+    
+    // Use the current processor to process the buffer.
+    (this->*processors[processorIndex])();
+}
+
+bool Synthesizer::isPlaying() {
+    return currentState != OFF;
+}
+
+int64_t Synthesizer::getVoiceIndex() {
+    return voiceIndex;   
+}
+
+void Synthesizer::nextSynth(int direction) {
+    // Rotate to the next synth.
+    processorIndex += direction;
+    if (processorIndex >= numSynths) {
+        processorIndex -= numSynths;
+    } else if (processorIndex < 0) {
+        processorIndex += numSynths;
+    }
+    
+    // If we are playing, restart the buffer.
+    if (isPlaying()) {
+        fromDisabled = true;
+        bufferIndex = 0;
+        currentState = FILL;  
+    }
+}
+
+int Synthesizer::getCurrentKey() {
+    return currentKey;   
+}
+
+// Processor Functions.
+
+void Synthesizer::processSine() {
+    if (currentState == FILL) {
+        // Create the sine wave.
+        buffer[bufferIndex] = velocity * sin(TWO_PI * float(bufferIndex) / float(bufferSize));
+        ++bufferIndex;
+        
+        // Check if we have reached the end of the buffer.
+        if (bufferIndex == bufferSize) {
+            bufferIndex = 0;
+            
+            // Check if there are new notes waiting in the queue.
+            if (nextBufferSize != -1) {
+                currentState = RELEASE;
+            } else {
+                currentState = SUSTAIN;
+            }   
+        }
+    } else {
+        identityProcess();    
+    }
+}
+
+void Synthesizer::processTriangle() {
+    if (currentState == FILL) {
+        // Create the triangle wave.
+        // Rotate pi/2 to remove phase offset.
+        int index = (bufferIndex + (bufferSize >> 2)) % bufferSize;
+        // Calculate linear function from -1 to 3
+        int sample = -1.0 + (4.0 * float(index) / float(bufferSize));
+        // Redirect second half of the line.
+        if (sample > 1.0) {
+            sample = -sample + 2.0;   
+        }
+        buffer[bufferIndex] = velocity * sample;
+        ++bufferIndex;
+        
+        // Check if we have reached the end of the buffer.
+        if (bufferIndex == bufferSize) {
+            bufferIndex = 0;
+            
+            // Check if there are new notes waiting in the queue.
+            if (nextBufferSize != -1) {
+                currentState = RELEASE;
+            } else {
+                currentState = SUSTAIN;
+            }   
+        }
+    } else {
+        identityProcess();    
+    }
+}
+
+void Synthesizer::processSquare() {
+    if (currentState == FILL) {
+        // Create the square wave.
+        buffer[bufferIndex] = bufferIndex < (bufferSize >> 1) ? -velocity : velocity;
+        ++bufferIndex;
+        
+        // Check if we have reached the end of the buffer.
+        if (bufferIndex == bufferSize) {
+            bufferIndex = 0;
+            
+            // Check if there are new notes waiting in the queue.
+            if (nextBufferSize != -1) {
+                currentState = RELEASE;
+            } else {
+                currentState = SUSTAIN;
+            }   
+        }
+    } else {
+        identityProcess();    
+    }
+}
+
+void Synthesizer::processSaw() {
+    if (currentState == FILL) {
+        // Create the saw wave.
+        buffer[bufferIndex] = velocity * (1.0 - 2.0 * float(bufferIndex) / float(bufferSize));
+        ++bufferIndex;
+        
+        // Check if we have reached the end of the buffer.
+        if (bufferIndex == bufferSize) {
+            bufferIndex = 0;
+            
+            // Check if there are new notes waiting in the queue.
+            if (nextBufferSize != -1) {
+                currentState = RELEASE;
+            } else {
+                currentState = SUSTAIN;
+            }   
+        }
+    } else {
+        identityProcess();    
+    }
+}
+
+void Synthesizer::identityProcess() {
+    if (currentState == RELEASE) {
+        // Attenuate the current buffer.
+        buffer[bufferIndex] *= -(float(bufferIndex) / float(bufferSize)) + 1.0;
+    }
+    
+    ++bufferIndex;
+        
+    // Check if we have reached the end of the buffer.
+    if (bufferIndex == bufferSize) {
+        bufferIndex = 0;
+        
+        // Check the queue to see if we have a new note waiting.
+        if (nextBufferSize != -1) {
+            if (currentState == SUSTAIN) {
+                currentState = RELEASE;   
+            } else {
+                bufferSize = nextBufferSize;
+                velocity = nextVelocity;
+                nextBufferSize = -1;
+                fromDisabled = false;
+                currentState = FILL;
+            }
+        } else if (currentState == RELEASE) {
+            // Disable the synthesizer.
+            currentState = OFF;
+            voiceIndex = -1;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Audio/Synthesizer.h	Wed Apr 13 19:46:28 2016 +0000
@@ -0,0 +1,116 @@
+/**
+ * The class representing a single monophonic voice.
+ * This class holds and processes its own buffer and play state.
+ *
+ * Note: This class also holds implementations for each of the different instruments.
+ * In a perfect OOP world this would be extracted out into an interface with a
+ *   concrete class for each instrument, but in order to keep overhead low, I
+ *   went for an array of member function pointers instead.
+ *
+ * @author Austin Suszek
+ */
+
+#ifndef AS_SYNTHESIZER_H
+#define AS_SYNTHESIZER_H
+
+#include "../Constants.h"
+#include "../mbed.h"
+
+/**
+ * An enum representing the possible states of the synthesizer.
+ */
+enum SynthState {
+    OFF,
+    FILL,
+    SUSTAIN,
+    RELEASE  
+};
+
+class Synthesizer {
+public:
+    
+    /**
+     * Constructor
+     */
+    Synthesizer();
+    
+    /**
+     * Signal the beginning of a note being pressed.
+     *
+     * @param key The integer representation of the note
+     * @param velocity (optional) The note velocity in the range of 0-127
+     */
+    void midiNoteOn(int key, int velocity);
+    
+    /**
+     * Signal the end of a note being pressed.
+     */
+    void midiNoteOff();
+    
+    /**
+     * Get the next sample to output.
+     */
+    float getSample();
+     
+    /**
+     * Process the current buffer.
+     */
+    void processBuffer();
+    
+    /**
+     * Returns false for SynthState OFF and true for all other states.
+     */
+    bool isPlaying();
+    
+    /**
+     * Getter for the voiceIndex variable.
+     */
+     int64_t getVoiceIndex(); 
+    
+    /**
+     * Switch to a new synth instrument.
+     *
+     * @param direction 1 for next, -1 for previous.
+     */
+    void nextSynth(int direction);
+    
+    /**
+     * A getter for the current key.
+     * It is always overwritten to the most recent key.
+     */
+    int getCurrentKey();
+    
+    /**
+     * Processor functions. These are responsible for all procesing of the buffer based on their instrument.
+     */
+    void processSine();
+    void processTriangle();
+    void processSquare();
+    void processSaw();
+
+private:
+
+    float buffer[(C::SAMPLE_RATE / C::MIN_FREQUENCY) + 1];
+    int bufferIndex;
+
+    SynthState currentState;
+    
+    int currentKey;
+    int bufferSize;
+    float velocity;
+    
+    int nextBufferSize;
+    float nextVelocity;
+    
+    int64_t voiceIndex;
+    static int64_t nextVoiceIndex;
+    bool fromDisabled;
+    
+    // A process that just outputs input.
+    void identityProcess();
+    
+    volatile int processorIndex;
+    
+};
+
+#endif
\ No newline at end of file
--- a/AudioEngine.cpp	Tue Apr 12 20:39:18 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/* 
- * The interface for all audio input and output.
- * This class acts as a container for individual voices.
- * It takes in MIDI events and handles processing and output.
- *
- * @author Austin Suszek
- */
- 
-#include "AudioEngine.h"
-
-#if USE_PWM
-PwmOut audioOut(p21);
-#else
-AnalogOut audioOut(p18);
-#endif
- 
-AudioEngine::AudioEngine() {
-    // Initialize the synthesizers.
-    for (int i = 0; i < C::MAX_POLYPHONY; i++) {
-        synthesizers[i] = Synthesizer();   
-    }
-    
-    #if USE_PWM
-    audioOut.period(1.0/200000.0);
-    #endif
-    
-    // Set up the sampler.
-    samplePeriod.attach(this, &AudioEngine::outputAudio, 1.0 / float(C::SAMPLE_RATE));
-}
-
-void AudioEngine::midiNoteOn(const int key, const int velocity) {
-    // Find the firt disabled voice or the one that has been playing longest.
-    int64_t min  = synthesizers[0].getVoiceIndex();
-    int minIndex = 0;
-    for (int i = 1; i < C::MAX_POLYPHONY; i++) {
-        int64_t voiceIndex = synthesizers[i].getVoiceIndex();
-        if (voiceIndex < min) {
-            min = voiceIndex;
-            minIndex = i;
-        }   
-    }
-    
-    // Send the note to the minimum voice.
-    synthesizers[minIndex].midiNoteOn(key, velocity);
-}
-
-void AudioEngine::midiNoteOff(const int key) {
-    for (int i = 0; i < C::MAX_POLYPHONY; i++) {
-        if (synthesizers[i].isPlaying() && synthesizers[i].getCurrentKey() == key) {
-            synthesizers[i].midiNoteOff();
-            break;
-        }
-    }
-}
-
-void AudioEngine::nextSynth(int direction) {
-    // Hand the command down to the synthesizers.
-    for (int i = 0; i < C::MAX_POLYPHONY; i++) {
-        synthesizers[i].nextSynth(direction);   
-    }
-}
-
-void AudioEngine::outputAudio() {
-    float output = 0.0;
-    
-    // Poll all of the synthesizers.
-    for (int i = 0; i < C::MAX_POLYPHONY; i++) {
-        if (synthesizers[i].isPlaying()) {
-            output += synthesizers[i].getSample();   
-        } 
-    }
-    
-    // Scale the output by the number of voices.
-    output /= float(C::MAX_POLYPHONY);
-    // Check that we do not clip.
-    if (output > 1.0) {
-        output = 1.0;
-    }
-    if (output < -1.0) {
-        output = -1.0;
-    }
-    // Map [-1, 1] range to [0, 1] range.
-    audioOut = (output + 1.0) / 2.0;
-    
-    // Go back and process the next sample on all voices.
-    for (int i = 0; i < C::MAX_POLYPHONY; i++) {
-        if (synthesizers[i].isPlaying()) {
-            synthesizers[i].processBuffer();   
-        } 
-    }
-}
\ No newline at end of file
--- a/AudioEngine.h	Tue Apr 12 20:39:18 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/**
- * The interface for all audio input and output.
- * This class acts as a container for individual voices.
- * It takes in MIDI events and handles processing and output.
- *
- * @author Austin Suszek
- */
-
-#ifndef AS_AUDIO_ENGINE_H
-#define AS_AUDIO_ENGINE_H
-
-#include "Constants.h"
-#include "mbed.h"
-#include "Synthesizer.h"
-
-class AudioEngine {
-public:
-
-    /**
-     * Constructor
-     */
-    AudioEngine();
-    
-    /**
-     * Signal the beginning of a note being pressed.
-     *
-     * @param key The integer representation of the note
-     * @param velocity (optional) The note velocity in the range of 0-127
-     */
-    void midiNoteOn(const int key, const int velocity = 0x7F);
-    
-    /**
-     * Signal the end of a note being pressed.
-     *
-     * @param key The integer representation of the note
-     */
-    void midiNoteOff(const int key);
-    
-    /**
-     * Switch to a new synth instrument.
-     *
-     * @param direction 1 for next, -1 for previous.
-     */
-    void nextSynth(int direction);
-    
-private:
-    
-    Ticker samplePeriod;
-    void outputAudio();
-    
-    Synthesizer synthesizers[C::MAX_POLYPHONY];
-    
-};
-
-#endif
\ No newline at end of file
--- a/Synthesizer.cpp	Tue Apr 12 20:39:18 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,250 +0,0 @@
-
-#include "Synthesizer.h"
-
-const float TWO_PI = 6.28318530717959;
-const int numSynths = 4;
-
-/**
- * A function that acts as an individual synthesizer.
- * It's job is to process the next sample at the current index
- *   based on the current state of the overall synthesizer.
- * Output should be in the range of [-1.0, 1.0] and saved back into the buffer.
- */
-typedef void (Synthesizer::*processorFunction)();
-
-// Array of pointers to all synthesizer functions.
-processorFunction processors[] = {
-        &Synthesizer::processSine,
-        &Synthesizer::processTriangle,
-        &Synthesizer::processSquare,
-        &Synthesizer::processSaw,
-};
-
-int64_t Synthesizer::nextVoiceIndex = 0;
-
-Synthesizer::Synthesizer() {
-    bufferIndex = 0;
-    currentState = OFF;
-    nextBufferSize = -1;
-    voiceIndex = -1;
-    processorIndex = 0;
-}
-
-void Synthesizer::midiNoteOn(int key, int velocity) {
-    float freq = 440.0 * std::pow(2.0, float(key - 69) / 12.0);
-    
-    // Make sure we are in bounds.
-    if (freq < C::MIN_FREQUENCY) {
-        #ifdef DEBUG
-        printf("Error: Note is below minimum frequency");
-        #endif
-        return;   
-    }
-    
-    currentKey = key;
-    int size = int((float(C::SAMPLE_RATE) / freq) + 0.5);
-    
-    if (currentState == OFF) {
-        // We can immediately play the new note.
-        bufferSize = size;
-        this->velocity = float(velocity) / 127.0;
-        
-        voiceIndex = Synthesizer::nextVoiceIndex;
-        ++Synthesizer::nextVoiceIndex;
-        fromDisabled = true;
-        currentState = FILL;
-    } else {
-         // Put the values in the queue for later.
-         nextBufferSize = size;  
-         nextVelocity = float(velocity) / 127.0;
-    } 
-}
-
-void Synthesizer::midiNoteOff() {
-    // Begin release of current note.
-    currentState = RELEASE;
-    
-    // Clear the queue.
-    nextBufferSize = -1; 
-}
-
-float Synthesizer::getSample() {
-    if (currentState == FILL && fromDisabled) {
-        // The buffer may contain the release of the previous note so just return 0.0
-        return 0.0; 
-    }
-    
-    // Simply return the next sample. Do not increment.
-    return buffer[bufferIndex];   
-}
-
-void Synthesizer::processBuffer() {
-    // Assert that we are playing.
-    if (currentState == OFF) {
-        #ifdef DEBUG
-        printf("Error: Attempting to process a disabled synthesizer.");   
-        #endif
-        return;
-    }
-    
-    // Use the current processor to process the buffer.
-    (this->*processors[processorIndex])();
-}
-
-bool Synthesizer::isPlaying() {
-    return currentState != OFF;
-}
-
-int64_t Synthesizer::getVoiceIndex() {
-    return voiceIndex;   
-}
-
-void Synthesizer::nextSynth(int direction) {
-    // Rotate to the next synth.
-    processorIndex += direction;
-    if (processorIndex >= numSynths) {
-        processorIndex -= numSynths;
-    } else if (processorIndex < 0) {
-        processorIndex += numSynths;
-    }
-    
-    // If we are playing, restart the buffer.
-    if (isPlaying()) {
-        fromDisabled = true;
-        bufferIndex = 0;
-        currentState = FILL;  
-    }
-}
-
-int Synthesizer::getCurrentKey() {
-    return currentKey;   
-}
-
-// Processor Functions.
-
-void Synthesizer::processSine() {
-    if (currentState == FILL) {
-        // Create the sine wave.
-        buffer[bufferIndex] = velocity * sin(TWO_PI * float(bufferIndex) / float(bufferSize));
-        ++bufferIndex;
-        
-        // Check if we have reached the end of the buffer.
-        if (bufferIndex == bufferSize) {
-            bufferIndex = 0;
-            
-            // Check if there are new notes waiting in the queue.
-            if (nextBufferSize != -1) {
-                currentState = RELEASE;
-            } else {
-                currentState = SUSTAIN;
-            }   
-        }
-    } else {
-        identityProcess();    
-    }
-}
-
-void Synthesizer::processTriangle() {
-    if (currentState == FILL) {
-        // Create the triangle wave.
-        // Rotate pi/2 to remove phase offset.
-        int index = (bufferIndex + (bufferSize >> 2)) % bufferSize;
-        // Calculate linear function from -1 to 3
-        int sample = -1.0 + (4.0 * float(index) / float(bufferSize));
-        // Redirect second half of the line.
-        if (sample > 1.0) {
-            sample = -sample + 2.0;   
-        }
-        buffer[bufferIndex] = velocity * sample;
-        ++bufferIndex;
-        
-        // Check if we have reached the end of the buffer.
-        if (bufferIndex == bufferSize) {
-            bufferIndex = 0;
-            
-            // Check if there are new notes waiting in the queue.
-            if (nextBufferSize != -1) {
-                currentState = RELEASE;
-            } else {
-                currentState = SUSTAIN;
-            }   
-        }
-    } else {
-        identityProcess();    
-    }
-}
-
-void Synthesizer::processSquare() {
-    if (currentState == FILL) {
-        // Create the square wave.
-        buffer[bufferIndex] = bufferIndex < (bufferSize >> 1) ? -velocity : velocity;
-        ++bufferIndex;
-        
-        // Check if we have reached the end of the buffer.
-        if (bufferIndex == bufferSize) {
-            bufferIndex = 0;
-            
-            // Check if there are new notes waiting in the queue.
-            if (nextBufferSize != -1) {
-                currentState = RELEASE;
-            } else {
-                currentState = SUSTAIN;
-            }   
-        }
-    } else {
-        identityProcess();    
-    }
-}
-
-void Synthesizer::processSaw() {
-    if (currentState == FILL) {
-        // Create the saw wave.
-        buffer[bufferIndex] = velocity * (1.0 - 2.0 * float(bufferIndex) / float(bufferSize));
-        ++bufferIndex;
-        
-        // Check if we have reached the end of the buffer.
-        if (bufferIndex == bufferSize) {
-            bufferIndex = 0;
-            
-            // Check if there are new notes waiting in the queue.
-            if (nextBufferSize != -1) {
-                currentState = RELEASE;
-            } else {
-                currentState = SUSTAIN;
-            }   
-        }
-    } else {
-        identityProcess();    
-    }
-}
-
-void Synthesizer::identityProcess() {
-    if (currentState == RELEASE) {
-        // Attenuate the current buffer.
-        buffer[bufferIndex] *= -(float(bufferIndex) / float(bufferSize)) + 1.0;
-    }
-    
-    ++bufferIndex;
-        
-    // Check if we have reached the end of the buffer.
-    if (bufferIndex == bufferSize) {
-        bufferIndex = 0;
-        
-        // Check the queue to see if we have a new note waiting.
-        if (nextBufferSize != -1) {
-            if (currentState == SUSTAIN) {
-                currentState = RELEASE;   
-            } else {
-                bufferSize = nextBufferSize;
-                velocity = nextVelocity;
-                nextBufferSize = -1;
-                fromDisabled = false;
-                currentState = FILL;
-            }
-        } else if (currentState == RELEASE) {
-            // Disable the synthesizer.
-            currentState = OFF;
-            voiceIndex = -1;
-        }
-    }
-}
\ No newline at end of file
--- a/Synthesizer.h	Tue Apr 12 20:39:18 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/**
- * The class representing a single monophonic voice.
- * This class holds and processes its own buffer and play state.
- *
- * Note: This class also holds implementations for each of the different instruments.
- * In a perfect OOP world this would be extracted out into an interface with a
- *   concrete class for each instrument, but in order to keep overhead low, I
- *   went for an array of member function pointers instead.
- *
- * @author Austin Suszek
- */
-
-#ifndef AS_SYNTHESIZER_H
-#define AS_SYNTHESIZER_H
-
-#include "Constants.h"
-#include "mbed.h"
-
-/**
- * An enum representing the possible states of the synthesizer.
- */
-enum SynthState {
-    OFF,
-    FILL,
-    SUSTAIN,
-    RELEASE  
-};
-
-class Synthesizer {
-public:
-    
-    /**
-     * Constructor
-     */
-    Synthesizer();
-    
-    /**
-     * Signal the beginning of a note being pressed.
-     *
-     * @param key The integer representation of the note
-     * @param velocity (optional) The note velocity in the range of 0-127
-     */
-    void midiNoteOn(int key, int velocity);
-    
-    /**
-     * Signal the end of a note being pressed.
-     */
-    void midiNoteOff();
-    
-    /**
-     * Get the next sample to output.
-     */
-    float getSample();
-     
-    /**
-     * Process the current buffer.
-     */
-    void processBuffer();
-    
-    /**
-     * Returns false for SynthState OFF and true for all other states.
-     */
-    bool isPlaying();
-    
-    /**
-     * Getter for the voiceIndex variable.
-     */
-     int64_t getVoiceIndex(); 
-    
-    /**
-     * Switch to a new synth instrument.
-     *
-     * @param direction 1 for next, -1 for previous.
-     */
-    void nextSynth(int direction);
-    
-    /**
-     * A getter for the current key.
-     * It is always overwritten to the most recent key.
-     */
-    int getCurrentKey();
-    
-    /**
-     * Processor functions. These are responsible for all procesing of the buffer based on their instrument.
-     */
-    void processSine();
-    void processTriangle();
-    void processSquare();
-    void processSaw();
-
-private:
-
-    float buffer[(C::SAMPLE_RATE / C::MIN_FREQUENCY) + 1];
-    int bufferIndex;
-
-    SynthState currentState;
-    
-    int currentKey;
-    int bufferSize;
-    float velocity;
-    
-    int nextBufferSize;
-    float nextVelocity;
-    
-    int64_t voiceIndex;
-    static int64_t nextVoiceIndex;
-    bool fromDisabled;
-    
-    // A process that just outputs input.
-    void identityProcess();
-    
-    volatile int processorIndex;
-    
-};
-
-#endif
\ No newline at end of file
--- a/main.cpp	Tue Apr 12 20:39:18 2016 +0000
+++ b/main.cpp	Wed Apr 13 19:46:28 2016 +0000
@@ -4,7 +4,7 @@
  * @author Nick Delfino
  */
 
-#include "AudioEngine.h"
+#include "Audio/AudioEngine.h"
 #include "Constants.h"
 #include "mbed.h"
 #include "PinDetect.h"