12-polyphonic "chiptune" MIDI synthesizer for LPC1768 (Standalone version)
Dependencies: ClockControl PowerControl mbed
GeminiCore.cpp
- Committer:
- kayekss
- Date:
- 2014-11-09
- Revision:
- 0:727737138ac5
- Child:
- 2:ca10e33bde0a
File content as of revision 0:727737138ac5:
#include "mbed.h" #include "GeminiCore.h" uint16_t const GeminiCore::samplingRate = 32000u; /** Constructor of class GeminiCore */ GeminiCore::GeminiCore(uint8_t numInstruments) { this->numInstruments = numInstruments; // Instantiate instrument list this->instrumentList = new Instrument[numInstruments]; for (uint8_t i = 0; i < numInstruments; i++) { this->instrumentList[i].enable(); this->instrumentList[i].setSamplingRate(GeminiCore::samplingRate); this->instrumentList[i].setWave(Wavetable::waveDefList[4]); } // Allocate bytes to preserve previous samples prevSample = new uint8_t[numInstruments]; // Initialize random seeds this->x8 = 77u; this->x16 = 5501u; } /** Destructor of class GeminiCore */ GeminiCore::~GeminiCore() { delete[] this->instrumentList; delete[] this->prevSample; } /** Make a sample - should be called periodically depending on the sampling rate */ uint16_t GeminiCore::makeSample() { Instrument* iThInst; Wavetable::wave_t iThWave; int32_t sample; int32_t iThSample; uint16_t phasePrev; uint32_t duration; uint8_t decayRatio; sample = 0; for (uint8_t i = 0; i < numInstruments; i++) { iThInst = &instrumentList[i]; iThWave = iThInst->getWave(); // Do nothing if the instrument is disabled or not sounding if (!iThInst->isEnable() || iThInst->getFrequency() == 0) { continue; } duration = iThInst->getDuration(); if (duration >> iThWave.decaySpeed >= 255 - iThWave.sustainLevel) { decayRatio = iThWave.sustainLevel; } else { decayRatio = 256 - (duration >> iThWave.decaySpeed); } switch (iThWave.wavetype) { case Wavetable::Noise: phasePrev = iThInst->getPhase(); iThInst->advancePhase(); // If necessary, generate new random value if ((iThInst->getPhase() >> 8) - (phasePrev >> 8) > 0) { prevSample[i] = rand16() >> 8; } iThSample = prevSample[i]; break; case Wavetable::LowPeriodNoise: phasePrev = iThInst->getPhase(); iThInst->advancePhase(); // If necessary, generate new random value if ((iThInst->getPhase() >> 8) - (phasePrev >> 8) > 0) { prevSample[i] = rand8(); } iThSample = prevSample[i]; break; default: iThInst->advancePhase(); iThSample = Wavetable::waveTableList[iThWave.wavetype][iThInst->getPhase() >> 8] - 128; } sample += iThSample * iThInst->getMasterVolume() * decayRatio; } sample >>= 10; if (sample > 32767) sample = 32767; if (sample < -32768) sample = -32768; return (uint16_t) (sample + 32768); } /** Enable i-th Instrument */ bool GeminiCore::enable(uint8_t i) { Instrument* iThInst = NULL; if (i >= numInstruments || instrumentList == NULL) { return false; } iThInst = &instrumentList[i]; if (iThInst == NULL) { return false; } iThInst->enable(); return true; } /** Disable i-th Instrument */ bool GeminiCore::disable(uint8_t i) { Instrument* iThInst = NULL; if (i >= numInstruments || instrumentList == NULL) { return false; } iThInst = &instrumentList[i]; if (iThInst == NULL) { return false; } iThInst->disable(); return true; } /** Note on i-th Instrument */ bool GeminiCore::noteOn(uint8_t i, uint16_t frequency, uint8_t velocity) { Instrument* iThInst = NULL; if (i >= numInstruments || instrumentList == NULL) { return false; } iThInst = &instrumentList[i]; if (iThInst == NULL) { return false; } iThInst->setFrequency(frequency); // @TODO pitch bend correction needed iThInst->setVelocity(velocity); return true; } /** Note off i-th Instrument */ bool GeminiCore::noteOff(uint8_t i) { Instrument* iThInst = NULL; if (i >= numInstruments || instrumentList == NULL) { return false; } iThInst = &instrumentList[i]; if (iThInst == NULL) { return false; } iThInst->setFrequency(0); return true; } /** Set volume (0..127) to i-th Instrument */ bool GeminiCore::volume(uint8_t i, uint8_t vo) { Instrument* iThInst = NULL; if (i >= numInstruments || instrumentList == NULL) { return false; } iThInst = &instrumentList[i]; if (iThInst == NULL) { return false; } iThInst->setVolume(vo << 1); // 0..127 => 0..254 return true; } /** Set expression (0..127) to i-th Instrument */ bool GeminiCore::expression(uint8_t i, uint8_t ex) { Instrument* iThInst = NULL; if (i >= numInstruments || instrumentList == NULL) { return false; } iThInst = &instrumentList[i]; if (iThInst == NULL) { return false; } iThInst->setExpression(ex << 1); // 0..127 => 0..254 return true; } bool GeminiCore::pitchBend(uint8_t i, int16_t pb) { // @TODO return true; } /** Set wave parameters to i-th Instrument */ bool GeminiCore::setWave(uint8_t i, Wavetable::wave_t w) { Instrument* iThInst = NULL; if (i >= numInstruments || instrumentList == NULL) { return false; } iThInst = &instrumentList[i]; if (iThInst == NULL) { return false; } iThInst->setWave(w); return true; } /** Get instrument list */ Instrument* GeminiCore::getInstrumentList() { return this->instrumentList; } /** Generate an 8-bit random number */ uint8_t GeminiCore::rand8() { x8 ^= x8 << 7; x8 ^= x8 >> 5; x8 ^= x8 << 3; return x8; } /** Generate a 16-bit random number */ uint16_t GeminiCore::rand16() { x16 ^= x16 << 13; x16 ^= x16 >> 9; x16 ^= x16 << 7; return x16; }