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