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

Dependencies:   mbed USBDevice PinDetect

Audio/Synthesizer.h

Committer:
asuszek
Date:
2016-04-21
Revision:
18:26d93c5b9bb6
Parent:
13:bb0ec927e458

File content as of revision 18:26d93c5b9bb6:

/**
 * 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"
#include "KarplusStrong.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, and process the buffer for the next period.
     */
    float getSample();
    
    /**
     * 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.
     * @return The new index being played.
     */
    int 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 processKarplusStrong();
    void processSine();
    void processTriangle();
    void processSquare();
    void processSaw();

private:

    float buffer[(C::SAMPLE_RATE / C::MIN_FREQUENCY) + 1];
    int bufferIndex;

    SynthState currentState;
    KarplusStrong karplusStrong;
    
    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();
    void checkFillBounds();
    
    volatile int processorIndex;
    
};

#endif