A MIDI piano synthesizer that implements the Karplus Strong physical modeling algorithm.
Dependencies: mbed USBDevice PinDetect
Audio/AudioEngine.cpp
- Committer:
- asuszek
- Date:
- 2016-04-13
- Revision:
- 9:1e012f67470c
- Parent:
- AudioEngine.cpp@ 6:688698f814c0
- Child:
- 13:bb0ec927e458
File content as of revision 9:1e012f67470c:
/* * 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(); } } }