A MIDI piano synthesizer that implements the Karplus Strong physical modeling algorithm.
Dependencies: mbed USBDevice PinDetect
Audio/AudioEngine.cpp
- Committer:
- asuszek
- Date:
- 2016-04-25
- Revision:
- 22:b800e1766647
- Parent:
- 18:26d93c5b9bb6
File content as of revision 22:b800e1766647:
/* * 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(); } outputSample = 0.0; #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; } } } int AudioEngine::nextSynth(int direction) { int nextIndex; // Hand the command down to the synthesizers. for (int i = 0; i < C::MAX_POLYPHONY; i++) { nextIndex = synthesizers[i].nextSynth(direction); } return nextIndex; } void AudioEngine::outputAudio() { // The first thing we do is output the last calculated sample. // Map [-1, 1] range to [0, 1] range. audioOut = (outputSample + 1.0) / 2.0; // Now reset output and calculate the next sample. outputSample = 0.0; // Poll all of the synthesizers. for (int i = 0; i < C::MAX_POLYPHONY; i++) { if (synthesizers[i].isPlaying()) { // Get the next sample. outputSample += synthesizers[i].getSample(); } } // Scale the output by the number of voices. outputSample /= float(C::MAX_POLYPHONY); // Check that we do not clip. if (outputSample > 1.0) { outputSample = 1.0; } if (outputSample < -1.0) { outputSample = -1.0; } }