andrewm@0: /* andrewm@0: * OscillatorBank.h andrewm@0: * andrewm@0: * Created on: May 23, 2014 andrewm@0: * Author: Victor Zappi and Andrew McPherson andrewm@0: */ andrewm@0: andrewm@0: #ifndef OSCILLATORBANK_H_ andrewm@0: #define OSCILLATORBANK_H_ andrewm@0: andrewm@0: andrewm@0: #include andrewm@0: andrewm@0: #include "spear_parser.h" andrewm@0: #include "ADSR.h" andrewm@0: #include "config.h" andrewm@0: andrewm@0: using namespace std; andrewm@0: andrewm@0: enum OscBankstates {bank_stopped, bank_playing, bank_toreset}; andrewm@0: andrewm@0: class OscillatorBank andrewm@0: { andrewm@0: public: andrewm@0: OscillatorBank(); andrewm@0: OscillatorBank(string filename, int hopsize=-1, int samplerate=44100); andrewm@0: OscillatorBank(char *filename, int hopsize=-1, int samplerate=44100); andrewm@0: ~OscillatorBank(); andrewm@0: float *oscillatorPhases; andrewm@0: float *oscillatorNormFrequencies; andrewm@0: float *oscillatorNormFreqDerivatives; andrewm@0: float *oscillatorAmplitudes; andrewm@0: float *oscillatorAmplitudeDerivatives; andrewm@0: float *oscStatNormFrequenciesMean; andrewm@0: float *oscStatNumHops; andrewm@0: OscBankstates state; andrewm@0: bool note; andrewm@0: int actPartNum; andrewm@0: unsigned int *actPart; andrewm@0: int hopCounter; andrewm@0: int lookupTableSize; andrewm@0: float *lookupTable; andrewm@0: float ampTh; andrewm@0: int hopNumTh; andrewm@0: float pitchMultiplier; andrewm@0: float freqMovement; andrewm@0: int filterNum; andrewm@0: float filterFreqs[5]; andrewm@0: float filterQ[5]; andrewm@0: float filterMaxF; andrewm@0: float filterAmpMinF; andrewm@0: float filterAmpMaxF; andrewm@0: float filterAmpMul; andrewm@0: andrewm@0: bool loadFile(string filename, int hopsize=-1, int samplerate=44100); andrewm@0: bool loadFile(char *filename, int hopsize=-1, int samplerate=44100); andrewm@0: bool initBank(int oversamp=1); andrewm@0: void resetOscillators(); andrewm@0: int getHopSize() { return hopSize; } andrewm@0: void nextHop(); andrewm@0: void setLoopHops(int start, int end); andrewm@0: void play(float vel); andrewm@0: void stop(); andrewm@0: void afterTouch(float vel); andrewm@0: int getEnvelopeState(); andrewm@0: float getFrequencyScaler(); andrewm@0: void setSpeed(float sp); andrewm@0: float getSpeed(); andrewm@0: float getMaxSpeed(); andrewm@0: float getMinSpeed(); andrewm@0: void setJumpHop(int hop); andrewm@0: int getLastHop(); andrewm@0: int getCurrentHop() { return currentHop; } andrewm@0: andrewm@0: private: andrewm@0: andrewm@0: bool loaded; andrewm@0: int numOfPartials; andrewm@0: int numOfOscillators; andrewm@0: int partialsHopSize; andrewm@0: int overSampling; andrewm@0: int hopSize; andrewm@0: int hopSizeReminder; andrewm@0: int oscBankHopSize; andrewm@0: float frequencyScaler; andrewm@0: float nyqNorm; andrewm@0: int lastHop; andrewm@0: int currentHop; andrewm@0: int loopDir; andrewm@0: int loopDirShift; andrewm@0: int loopStartHop; andrewm@0: int loopEndHop; andrewm@0: int *indicesMapping; andrewm@0: float *phaseCopies; andrewm@0: float *oscillatorNextNormFreq; andrewm@0: float *oscillatorNextAmp; andrewm@0: float *nextNormFreqCopies; andrewm@0: float *nextAmpCopies; andrewm@0: float *freqFixedDeltas; andrewm@0: float *ampFixedDeltas; andrewm@0: bool *nyquistCut; andrewm@0: Spear_parser parser; andrewm@0: Partials *partials; andrewm@0: ADSR adsr; andrewm@0: float minAttackTime; andrewm@0: float deltaAttackTime; andrewm@0: float minReleaseTime; andrewm@0: float deltaReleaseTime; andrewm@0: int envState; andrewm@0: int rate; andrewm@0: float speed; andrewm@0: float nextSpeed; andrewm@0: float maxSpeed; andrewm@0: float minSpeed; andrewm@0: int jumpHop; andrewm@0: float adsrVal; andrewm@0: float prevAdsrVal; andrewm@0: float prevAmpTh; andrewm@0: int prevHopNumTh; andrewm@0: float prevPitchMultiplier; andrewm@0: float prevFreqMovement; andrewm@0: int prevFilterNum; andrewm@0: float prevFilterFreqs[5]; andrewm@0: float prevFilterQ[5]; andrewm@0: andrewm@0: bool loader(char *filename, int hopsize=-1, int samplerate=44100); andrewm@0: void addFakeOsc(); andrewm@0: void nextOscBankHop(); andrewm@0: void nextPartialHop(); andrewm@0: int jumpToHop(); andrewm@0: void setDirection(int dir); andrewm@0: int nextEnvState(); andrewm@0: void checkDirection(); andrewm@0: void checkSpeed(); andrewm@0: int checkJump(); andrewm@0: bool checkOversampling(); andrewm@0: void updatePrevControls(); andrewm@0: float calculateParDamping(int parIndex, int hopNTh, float adsrVl, float nextFreq, andrewm@0: int filNum, float *filFreq, float *filQ); andrewm@0: }; andrewm@0: andrewm@0: inline bool OscillatorBank::loadFile(string filename, int hopsize, int samplerate) andrewm@0: { andrewm@0: return loader((char *)filename.c_str(), hopsize, samplerate); andrewm@0: } andrewm@0: andrewm@0: inline bool OscillatorBank::loadFile(char *filename, int hopsize, int samplerate) andrewm@0: { andrewm@0: return loader(filename, hopsize, samplerate); andrewm@0: } andrewm@0: andrewm@0: inline void OscillatorBank::setLoopHops(int start, int end) andrewm@0: { andrewm@0: if(start > end) andrewm@0: end = start; andrewm@0: andrewm@0: if(start<0) andrewm@0: start = 0; andrewm@0: else if(start>lastHop) andrewm@0: start = 0; andrewm@0: if(end < 1) andrewm@0: end = 1; andrewm@0: end = (end<=lastHop) ? end : lastHop; andrewm@0: andrewm@0: // set it, take into consideration hop oversampling andrewm@0: loopStartHop = start*overSampling; andrewm@0: loopEndHop = end*overSampling; andrewm@0: } andrewm@0: andrewm@0: inline void OscillatorBank::stop() andrewm@0: { andrewm@0: note = false; andrewm@0: adsr.gate(0); andrewm@0: } andrewm@0: andrewm@0: inline float OscillatorBank::getFrequencyScaler() andrewm@0: { andrewm@0: return frequencyScaler; andrewm@0: } andrewm@0: andrewm@0: inline void OscillatorBank::afterTouch(float vel) andrewm@0: { andrewm@0: hopNumTh = log((1-vel)+1)/log(2)*20000; andrewm@0: if(adsr.getState()==env_attack) andrewm@0: adsr.setAttackRate( (minAttackTime + ( (1-vel)*deltaAttackTime )) * rate ); andrewm@0: adsr.setReleaseRate( (minReleaseTime+(1-vel)*deltaReleaseTime)* rate ); andrewm@0: } andrewm@0: andrewm@0: inline int OscillatorBank::getEnvelopeState() andrewm@0: { andrewm@0: return envState; andrewm@0: } andrewm@0: andrewm@0: inline void OscillatorBank::setSpeed(float sp) andrewm@0: { andrewm@0: nextSpeed = sp; andrewm@0: } andrewm@0: andrewm@0: inline float OscillatorBank::getSpeed() andrewm@0: { andrewm@0: return speed; andrewm@0: } andrewm@0: andrewm@0: inline float OscillatorBank::getMaxSpeed() andrewm@0: { andrewm@0: return maxSpeed; andrewm@0: } andrewm@0: andrewm@0: inline float OscillatorBank::getMinSpeed() andrewm@0: { andrewm@0: return minSpeed; andrewm@0: } andrewm@0: andrewm@0: inline void OscillatorBank::setJumpHop(int hop) andrewm@0: { andrewm@0: if(hop<0) andrewm@0: return; andrewm@0: hop = (hop<=lastHop) ? hop : lastHop; andrewm@0: jumpHop = hop; andrewm@0: } andrewm@0: andrewm@0: inline void OscillatorBank::setDirection(int dir) andrewm@0: { andrewm@0: if(dir>=0) andrewm@0: { andrewm@0: loopDir = 1; andrewm@0: loopDirShift = 0; andrewm@0: } andrewm@0: else andrewm@0: { andrewm@0: loopDir = -1; andrewm@0: loopDirShift = 1; andrewm@0: } andrewm@0: } andrewm@0: andrewm@0: inline int OscillatorBank::getLastHop() andrewm@0: { andrewm@0: return lastHop; andrewm@0: } andrewm@0: #endif /* OSCILLATORBANK_H_ */