```cpp
//WavetableSynth.cpp
//
//Steven Kugies
//Assignment #9
//CS245
//Spring 2023
#include "WavetableSynth.h"
#include <iostream>
WavetableSynth::WavetableSynth(int devno, int R) : MidiIn(devno), rate(1.0f / R), audioData_("WavetableSynth.wav")
{
for(int i = 0; i < 10; ++i)
resampler_[i] = new Resample(&audioData_, 0, 1, 27862, 30201);
MidiIn::start();
}
WavetableSynth::~WavetableSynth(void)
{
MidiIn::stop();
for (int i = 0; i < 10; ++i)
delete resampler_[i];
}
float WavetableSynth::getValue(void)
{
float value = 0;
const float vibratoPitchShift = vibratoDepth_ * sin(lfo_argument);
const float netPitchShift = pitchWheelShift_ + vibratoPitchShift;
for(unsigned int i = 0; i < notes.size(); ++i)
{
resampler_[i]->setPitchOffset(notes[i].pitch + netPitchShift);
const float noteValue = (440.0f/114.0f) * resampler_[i]->getValue() * notes[i].adsr.getValue();
value += notes[i].gainFactor * noteValue;
}
return value * globalVolume_;
}
void WavetableSynth::incrementTime(void)
{
for (Note& n : notes)
{
n.time += rate;
n.adsr.incrementTime();
}
for(int i = 0; i < notes.size(); ++i)
resampler_[i]->incrementTime();
lfo_argument += lfo_dargument;
}
void WavetableSynth::onNoteOn(int channel, int note, int velocity)
{
//check if note is vector already
for(unsigned int i = 0; i < notes.size(); ++i)
{
if(notes[i].index == note)
{
notes[i].adsr.reset();
resampler_[i]->reset();
std::rotate(notes.begin() + i, notes.begin() + i+1, notes.end());
for(int j = i; j < 9; ++j)
{
std::swap(resampler_[j], resampler_[j + 1]);
}
return;
}
}
//check if vector is full
if(notes.size() > 9)
notes.erase(notes.begin());
//add note to vector
Note n{};
n.index = note;
n.gainFactor = velocity / 127.0f;
n.pitch = (note - 69.0f) * 100.0f;
n.time = 0;
notes.push_back(n);
resampler_[notes.size()-1]->reset();
}
void WavetableSynth::onNoteOff(int channel, int note)
{
int index = 0;
for (unsigned int i = 0; i < notes.size(); i++)
{
if (notes[i].index == note)
{
index = i;
notes[i].adsr.sustainOff();
break;
}
}
for(int i = index; i > 0 ; --i)
{
if (notes[i-1].adsr.getMode() == ADSR::RELEASE)
break;
std::swap(notes[i], notes[i - 1]);
std::swap(resampler_[i], resampler_[i - 1]);
}
}
void WavetableSynth::onPitchWheelChange(int channel, float value)
{
pitchWheelShift_ = value * 200.0f;
}
void WavetableSynth::onModulationWheelChange(int channel, int value)
{
vibratoDepth_ = (value / 127.0f) * 200.0f;
}
void WavetableSynth::onVolumeChange(int channel, int level)
{
globalVolume_ = level / 127.0f;
}
```