A MIDI piano synthesizer that implements the Karplus Strong physical modeling algorithm.

Dependencies:   mbed USBDevice PinDetect

Committer:
asuszek
Date:
Sun Apr 17 21:35:23 2016 +0000
Revision:
13:bb0ec927e458
Parent:
9:1e012f67470c
Child:
18:26d93c5b9bb6
Implemented basic Karplus Strong. The sample rate had to be halved in order to process the algorithm for each sample without crashing.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
asuszek 6:688698f814c0 1 /**
asuszek 6:688698f814c0 2 * The class representing a single monophonic voice.
asuszek 6:688698f814c0 3 * This class holds and processes its own buffer and play state.
asuszek 6:688698f814c0 4 *
asuszek 6:688698f814c0 5 * Note: This class also holds implementations for each of the different instruments.
asuszek 6:688698f814c0 6 * In a perfect OOP world this would be extracted out into an interface with a
asuszek 6:688698f814c0 7 * concrete class for each instrument, but in order to keep overhead low, I
asuszek 6:688698f814c0 8 * went for an array of member function pointers instead.
asuszek 6:688698f814c0 9 *
asuszek 6:688698f814c0 10 * @author Austin Suszek
asuszek 6:688698f814c0 11 */
asuszek 6:688698f814c0 12
asuszek 6:688698f814c0 13 #ifndef AS_SYNTHESIZER_H
asuszek 6:688698f814c0 14 #define AS_SYNTHESIZER_H
asuszek 6:688698f814c0 15
asuszek 9:1e012f67470c 16 #include "../Constants.h"
asuszek 9:1e012f67470c 17 #include "../mbed.h"
asuszek 13:bb0ec927e458 18 #include "KarplusStrong.h"
asuszek 6:688698f814c0 19
asuszek 6:688698f814c0 20 /**
asuszek 6:688698f814c0 21 * An enum representing the possible states of the synthesizer.
asuszek 6:688698f814c0 22 */
asuszek 6:688698f814c0 23 enum SynthState {
asuszek 6:688698f814c0 24 OFF,
asuszek 6:688698f814c0 25 FILL,
asuszek 6:688698f814c0 26 SUSTAIN,
asuszek 6:688698f814c0 27 RELEASE
asuszek 6:688698f814c0 28 };
asuszek 6:688698f814c0 29
asuszek 6:688698f814c0 30 class Synthesizer {
asuszek 6:688698f814c0 31 public:
asuszek 6:688698f814c0 32
asuszek 6:688698f814c0 33 /**
asuszek 6:688698f814c0 34 * Constructor
asuszek 6:688698f814c0 35 */
asuszek 6:688698f814c0 36 Synthesizer();
asuszek 6:688698f814c0 37
asuszek 6:688698f814c0 38 /**
asuszek 6:688698f814c0 39 * Signal the beginning of a note being pressed.
asuszek 6:688698f814c0 40 *
asuszek 6:688698f814c0 41 * @param key The integer representation of the note
asuszek 6:688698f814c0 42 * @param velocity (optional) The note velocity in the range of 0-127
asuszek 6:688698f814c0 43 */
asuszek 6:688698f814c0 44 void midiNoteOn(int key, int velocity);
asuszek 6:688698f814c0 45
asuszek 6:688698f814c0 46 /**
asuszek 6:688698f814c0 47 * Signal the end of a note being pressed.
asuszek 6:688698f814c0 48 */
asuszek 6:688698f814c0 49 void midiNoteOff();
asuszek 6:688698f814c0 50
asuszek 6:688698f814c0 51 /**
asuszek 13:bb0ec927e458 52 * Get the next sample to output, and process the buffer for the next period.
asuszek 6:688698f814c0 53 */
asuszek 6:688698f814c0 54 float getSample();
asuszek 6:688698f814c0 55
asuszek 6:688698f814c0 56 /**
asuszek 6:688698f814c0 57 * Returns false for SynthState OFF and true for all other states.
asuszek 6:688698f814c0 58 */
asuszek 6:688698f814c0 59 bool isPlaying();
asuszek 6:688698f814c0 60
asuszek 6:688698f814c0 61 /**
asuszek 6:688698f814c0 62 * Getter for the voiceIndex variable.
asuszek 6:688698f814c0 63 */
asuszek 6:688698f814c0 64 int64_t getVoiceIndex();
asuszek 6:688698f814c0 65
asuszek 6:688698f814c0 66 /**
asuszek 6:688698f814c0 67 * Switch to a new synth instrument.
asuszek 6:688698f814c0 68 *
asuszek 6:688698f814c0 69 * @param direction 1 for next, -1 for previous.
asuszek 6:688698f814c0 70 */
asuszek 6:688698f814c0 71 void nextSynth(int direction);
asuszek 6:688698f814c0 72
asuszek 6:688698f814c0 73 /**
asuszek 6:688698f814c0 74 * A getter for the current key.
asuszek 6:688698f814c0 75 * It is always overwritten to the most recent key.
asuszek 6:688698f814c0 76 */
asuszek 6:688698f814c0 77 int getCurrentKey();
asuszek 6:688698f814c0 78
asuszek 6:688698f814c0 79 /**
asuszek 6:688698f814c0 80 * Processor functions. These are responsible for all procesing of the buffer based on their instrument.
asuszek 6:688698f814c0 81 */
asuszek 13:bb0ec927e458 82 void processKarplusStrong();
asuszek 6:688698f814c0 83 void processSine();
asuszek 6:688698f814c0 84 void processTriangle();
asuszek 6:688698f814c0 85 void processSquare();
asuszek 6:688698f814c0 86 void processSaw();
asuszek 6:688698f814c0 87
asuszek 6:688698f814c0 88 private:
asuszek 6:688698f814c0 89
asuszek 6:688698f814c0 90 float buffer[(C::SAMPLE_RATE / C::MIN_FREQUENCY) + 1];
asuszek 6:688698f814c0 91 int bufferIndex;
asuszek 6:688698f814c0 92
asuszek 6:688698f814c0 93 SynthState currentState;
asuszek 13:bb0ec927e458 94 KarplusStrong karplusStrong;
asuszek 6:688698f814c0 95
asuszek 6:688698f814c0 96 int currentKey;
asuszek 6:688698f814c0 97 int bufferSize;
asuszek 6:688698f814c0 98 float velocity;
asuszek 6:688698f814c0 99
asuszek 6:688698f814c0 100 int nextBufferSize;
asuszek 6:688698f814c0 101 float nextVelocity;
asuszek 6:688698f814c0 102
asuszek 6:688698f814c0 103 int64_t voiceIndex;
asuszek 6:688698f814c0 104 static int64_t nextVoiceIndex;
asuszek 6:688698f814c0 105 bool fromDisabled;
asuszek 6:688698f814c0 106
asuszek 6:688698f814c0 107 // A process that just outputs input.
asuszek 6:688698f814c0 108 void identityProcess();
asuszek 13:bb0ec927e458 109 void checkFillBounds();
asuszek 6:688698f814c0 110
asuszek 6:688698f814c0 111 volatile int processorIndex;
asuszek 6:688698f814c0 112
asuszek 6:688698f814c0 113 };
asuszek 6:688698f814c0 114
asuszek 6:688698f814c0 115 #endif