mirror of
https://github.com/yokemura/Magical8bitPlug2.git
synced 2025-05-24 23:00:21 -04:00
148 lines
4.6 KiB
C++
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);
|
|
}
|
|
|