Austin Suszek / Mbed 2 deprecated MIDISynthesizer

Dependencies:   mbed USBDevice PinDetect

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AudioEngine.cpp Source File

AudioEngine.cpp

00001 /* 
00002  * The interface for all audio input and output.
00003  * This class acts as a container for individual voices.
00004  * It takes in MIDI events and handles processing and output.
00005  *
00006  * @author Austin Suszek
00007  */
00008  
00009 #include "AudioEngine.h"
00010 
00011 #if USE_PWM
00012 PwmOut audioOut(p21);
00013 #else
00014 AnalogOut audioOut(p18);
00015 #endif
00016  
00017 AudioEngine::AudioEngine() {
00018     // Initialize the synthesizers.
00019     for (int i = 0; i < C::MAX_POLYPHONY; i++) {
00020         synthesizers[i] = Synthesizer();   
00021     }
00022     
00023     outputSample = 0.0;
00024     
00025     #if USE_PWM
00026     audioOut.period(1.0/200000.0);
00027     #endif
00028     
00029     // Set up the sampler.
00030     samplePeriod.attach(this, &AudioEngine::outputAudio, 1.0 / float(C::SAMPLE_RATE));
00031 }
00032 
00033 void AudioEngine::midiNoteOn(const int key, const int velocity) {
00034     // Find the firt disabled voice or the one that has been playing longest.
00035     int64_t min  = synthesizers[0].getVoiceIndex();
00036     int minIndex = 0;
00037     for (int i = 1; i < C::MAX_POLYPHONY; i++) {
00038         int64_t voiceIndex = synthesizers[i].getVoiceIndex();
00039         if (voiceIndex < min) {
00040             min = voiceIndex;
00041             minIndex = i;
00042         }   
00043     }
00044     
00045     // Send the note to the minimum voice.
00046     synthesizers[minIndex].midiNoteOn(key, velocity);
00047 }
00048 
00049 void AudioEngine::midiNoteOff(const int key) {
00050     for (int i = 0; i < C::MAX_POLYPHONY; i++) {
00051         if (synthesizers[i].isPlaying() && synthesizers[i].getCurrentKey() == key) {
00052             synthesizers[i].midiNoteOff();
00053             break;
00054         }
00055     }
00056 }
00057 
00058 int AudioEngine::nextSynth(int direction) {
00059     int nextIndex;
00060     // Hand the command down to the synthesizers.
00061     for (int i = 0; i < C::MAX_POLYPHONY; i++) {
00062         nextIndex = synthesizers[i].nextSynth(direction);   
00063     }
00064     return nextIndex;
00065 }
00066 
00067 void AudioEngine::outputAudio() {
00068     // The first thing we do is output the last calculated sample.
00069     // Map [-1, 1] range to [0, 1] range.
00070     audioOut = (outputSample + 1.0) / 2.0;
00071     
00072     // Now reset output and calculate the next sample.
00073     outputSample = 0.0;
00074     
00075     // Poll all of the synthesizers.
00076     for (int i = 0; i < C::MAX_POLYPHONY; i++) {
00077         if (synthesizers[i].isPlaying()) {
00078             // Get the next sample.
00079             outputSample += synthesizers[i].getSample();   
00080         } 
00081     }
00082     
00083     // Scale the output by the number of voices.
00084     outputSample /= float(C::MAX_POLYPHONY);
00085     // Check that we do not clip.
00086     if (outputSample > 1.0) {
00087         outputSample = 1.0;
00088     }
00089     if (outputSample < -1.0) {
00090         outputSample = -1.0;
00091     }
00092 }