Magical8bitPlug2/Source/CustomSynth.cpp

148 lines
4.6 KiB
C++

/*
==============================================================================
CustomSynth.cpp
Created: 17 May 2021 11:29:59pm
Author: 除村武志
==============================================================================
*/
#include "CustomSynth.h"
#include "BaseVoice.h"
#include "TonalVoice.h"
#include "PluginProcessor.h"
CustomSynth::CustomSynth(Magical8bitPlug2AudioProcessor& p) : processor(p) {}
TonalVoice* CustomSynth::getVoiceIfShouldProcessInMonoMode() {
if (!processor.settingRefs.isMonophonic()) {
return nullptr;
}
if (processor.settingRefs.monophonicBehavior() == kNonLegato) {
return nullptr;
}
// Try casting into TonalVoice* and return it if success(otherwise returns nullptr)
return dynamic_cast<TonalVoice *>(voices.getFirst());
}
void CustomSynth::noteOn(int midiChannel, int midiNoteNumber, float velocity) {
TonalVoice *voice = getVoiceIfShouldProcessInMonoMode();
if (voice == nullptr) {
Synthesiser::noteOn(midiChannel, midiNoteNumber, velocity);
return;
}
// Mono
// Start thread guard
const ScopedLock sl (lock);
if (voice->isKeyDown()) {
// Already key on
switch (processor.settingRefs.monophonicBehavior()) {
case kLegato:
voice->addLegatoNote(midiNoteNumber, velocity);
break;
case kArpeggioUp:
voice->addArpeggioNoteAscending(midiNoteNumber);
break;
case kArpeggioDown:
voice->addArpeggioNoteDescending(midiNoteNumber);
break;
default:
// no-op
break;
}
} else {
switch (processor.settingRefs.monophonicBehavior()) {
case kLegato:
// start note and set legato mode
Synthesiser::noteOn(midiChannel, midiNoteNumber, velocity);
voice->setLegatoMode(*(processor.settingRefs.portamentoTime), midiChannel);
break;
case kArpeggioUp:
case kArpeggioDown:
// start note and calc arpeggio interval
Synthesiser::noteOn(midiChannel, midiNoteNumber, velocity);
voice->setArpeggioMode(calcArpeggioInterval(), midiChannel);
break;
default:
// no-op
break;
}
}
}
double CustomSynth::calcArpeggioInterval() {
switch (processor.settingRefs.apreggioIntervalType()) {
case k1frame:
return 1.0 / 60.0;
case k2frames:
return 1.0 / 30.0;
case k3frames:
return 1.0 / 20.0;
case k64th:
return 240.0 / (processor.getCurrentBPM() * 64);
case k48th:
return 240.0 / (processor.getCurrentBPM() * 48);
case k32nd:
return 240.0 / (processor.getCurrentBPM() * 32);
case k24th:
return 240.0 / (processor.getCurrentBPM() * 24);
case kSlider:
return *(processor.settingRefs.arpeggioIntervalSliderValue);
default:
return 1.0 / 60.0;
break;
}
}
void CustomSynth::noteOff(int midiChannel, int midiNoteNumber, float velocity, bool allowTailOff) {
TonalVoice *voice = getVoiceIfShouldProcessInMonoMode();
if (voice == nullptr) {
Synthesiser::noteOff(midiChannel, midiNoteNumber, velocity, allowTailOff);
return;
}
// mono
// Start thread guard
const ScopedLock sl (lock);
if (!voice->isKeyDown()) {
// key is already off
return;
}
switch (processor.settingRefs.monophonicBehavior()) {
case kLegato:
{
int numBuffer = voice->removeLegatoNote(midiNoteNumber);
if (numBuffer < 1) {
Synthesiser::noteOff(voice->primaryMidiChannel, voice->getCurrentlyPlayingNote(), velocity, allowTailOff);
}
}
break;
case kArpeggioUp:
case kArpeggioDown:
{
int numBuffer = voice->removeArpeggioNote(midiNoteNumber);
if (numBuffer < 1) {
Synthesiser::noteOff(voice->primaryMidiChannel, voice->getCurrentlyPlayingNote(), velocity, allowTailOff);
}
}
break;
default:
break;
}
}
void CustomSynth::allNotesOff (const int midiChannel, const bool allowTailOff) {
Synthesiser::allNotesOff(midiChannel, allowTailOff);
}