|
|
|
@ -15,6 +15,17 @@ namespace WaveSabreCore
|
|
|
|
|
VibratoAmount = 0.0f; |
|
|
|
|
|
|
|
|
|
Rise = 0.0f; |
|
|
|
|
Slide = 0.0f; |
|
|
|
|
|
|
|
|
|
voiceMode = VoiceMode::Polyphonic; |
|
|
|
|
monoActive = false; |
|
|
|
|
noteCount = 0; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < maxActiveNotes; i++) |
|
|
|
|
{ |
|
|
|
|
activeNotes[i] = false; |
|
|
|
|
noteLog[i] = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
clearEvents(); |
|
|
|
|
} |
|
|
|
@ -48,22 +59,89 @@ namespace WaveSabreCore
|
|
|
|
|
case EventType::NoteOn: |
|
|
|
|
{ |
|
|
|
|
int j = VoicesUnisono; |
|
|
|
|
for (int k = 0; j && k < maxVoices; k++) |
|
|
|
|
switch (voiceMode) |
|
|
|
|
{ |
|
|
|
|
if (!voices[k]->IsOn) |
|
|
|
|
case VoiceMode::Polyphonic: |
|
|
|
|
default: |
|
|
|
|
for (int k = 0; j && k < maxVoices; k++) |
|
|
|
|
{ |
|
|
|
|
if (!voices[k]->IsOn) |
|
|
|
|
{ |
|
|
|
|
j--; |
|
|
|
|
float f = (float)j / (VoicesUnisono > 1 ? (float)(VoicesUnisono - 1) : 1.0f); |
|
|
|
|
voices[k]->NoteOn(e->Note, e->Velocity, f * VoicesDetune, (f - .5f) * (VoicesPan * 2.0f - 1.0f) + .5f); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case VoiceMode::MonoLegatoTrill: |
|
|
|
|
activeNotes[e->Note] = true; |
|
|
|
|
noteLog[noteCount] = e->Note; |
|
|
|
|
noteCount++; |
|
|
|
|
if (!monoActive) // no current note active, start new one
|
|
|
|
|
{ |
|
|
|
|
monoActive = true; |
|
|
|
|
for (int k = 0; j && k < maxVoices; k++) |
|
|
|
|
{ |
|
|
|
|
if (!voices[k]->IsOn) |
|
|
|
|
{ |
|
|
|
|
j--; |
|
|
|
|
float f = (float)j / (VoicesUnisono > 1 ? (float)(VoicesUnisono - 1) : 1.0f); |
|
|
|
|
voices[k]->NoteOn(e->Note, e->Velocity, f * VoicesDetune, (f - .5f) * (VoicesPan * 2.0f - 1.0f) + .5f); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else // note active, slide to new note
|
|
|
|
|
{ |
|
|
|
|
j--; |
|
|
|
|
float f = (float)j / (VoicesUnisono > 1 ? (float)(VoicesUnisono - 1) : 1.0f); |
|
|
|
|
voices[k]->NoteOn(e->Note, e->Velocity, f * VoicesDetune, (f - .5f) * (VoicesPan * 2.0f - 1.0f) + .5f); |
|
|
|
|
for (int j = 0; j < maxVoices; j++) |
|
|
|
|
{ |
|
|
|
|
if (voices[j]->IsOn) |
|
|
|
|
voices[j]->NoteSlide(e->Note); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case EventType::NoteOff: |
|
|
|
|
for (int j = 0; j < maxVoices; j++) |
|
|
|
|
switch (voiceMode) |
|
|
|
|
{ |
|
|
|
|
if (voices[j]->IsOn && voices[j]->Note == e->Note) voices[j]->NoteOff(); |
|
|
|
|
case VoiceMode::Polyphonic: |
|
|
|
|
default: |
|
|
|
|
for (int j = 0; j < maxVoices; j++) |
|
|
|
|
{ |
|
|
|
|
if (voices[j]->IsOn && voices[j]->Note == e->Note) voices[j]->NoteOff(); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case VoiceMode::MonoLegatoTrill: |
|
|
|
|
activeNotes[e->Note] = false; |
|
|
|
|
if (e->Note == noteLog[noteCount - 1]) // note off is last note played, find last active note
|
|
|
|
|
{ |
|
|
|
|
for (; noteCount > 0; noteCount--) |
|
|
|
|
{ |
|
|
|
|
if (activeNotes[noteLog[noteCount - 1]]) |
|
|
|
|
{ |
|
|
|
|
for (int j = 0; j < maxVoices; j++) |
|
|
|
|
{ |
|
|
|
|
if (voices[j]->IsOn) |
|
|
|
|
voices[j]->NoteSlide(noteLog[noteCount - 1]); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (noteCount == 0) // no notes left, switch off the voices
|
|
|
|
|
{ |
|
|
|
|
monoActive = false; |
|
|
|
|
for (int j = 0; j < maxActiveNotes; j++) activeNotes[j] = false; |
|
|
|
|
for (int j = 0; j < maxVoices; j++) |
|
|
|
|
{ |
|
|
|
|
if (voices[j]->IsOn) |
|
|
|
|
voices[j]->NoteOff(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
events[i].Type = EventType::None; |
|
|
|
@ -96,6 +174,9 @@ namespace WaveSabreCore
|
|
|
|
|
{ |
|
|
|
|
if (voices[i]->IsOn) voices[i]->NoteOff(); |
|
|
|
|
} |
|
|
|
|
monoActive = false; |
|
|
|
|
noteCount = 0; |
|
|
|
|
for (int i = 0; i < maxActiveNotes; i++) activeNotes[i] = false; |
|
|
|
|
clearEvents(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -128,6 +209,21 @@ namespace WaveSabreCore
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SynthDevice::SetVoiceMode(VoiceMode voiceMode) |
|
|
|
|
{ |
|
|
|
|
if (this->voiceMode != voiceMode) |
|
|
|
|
{ |
|
|
|
|
AllNotesOff(); |
|
|
|
|
for (int i = 0; i < maxVoices; i++) voices[i]->IsOn = false; |
|
|
|
|
this->voiceMode = voiceMode; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
VoiceMode SynthDevice::GetVoiceMode() const |
|
|
|
|
{ |
|
|
|
|
return voiceMode; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SynthDevice::Voice::Voice() |
|
|
|
|
{ |
|
|
|
|
IsOn = false; |
|
|
|
@ -142,10 +238,36 @@ namespace WaveSabreCore
|
|
|
|
|
Note = note; |
|
|
|
|
Detune = detune; |
|
|
|
|
Pan = pan; |
|
|
|
|
currentNote = (double)note; |
|
|
|
|
slideActive = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SynthDevice::Voice::NoteOff() |
|
|
|
|
void SynthDevice::Voice::NoteOff() { } |
|
|
|
|
|
|
|
|
|
void SynthDevice::Voice::NoteSlide(int note) |
|
|
|
|
{ |
|
|
|
|
slideActive = true; |
|
|
|
|
destinationNote = note; |
|
|
|
|
|
|
|
|
|
double slideTime = 10.f * Helpers::Pow(this->SynthDevice()->Slide,4.0); |
|
|
|
|
slideDelta = ((double)note - currentNote) / (Helpers::CurrentSampleRate * slideTime); |
|
|
|
|
slideSamples = (int)(Helpers::CurrentSampleRate * slideTime); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
double SynthDevice::Voice::GetNote() |
|
|
|
|
{ |
|
|
|
|
if (slideActive) |
|
|
|
|
{ |
|
|
|
|
currentNote += slideDelta; |
|
|
|
|
slideSamples--; |
|
|
|
|
if (slideSamples < 0) |
|
|
|
|
{ |
|
|
|
|
Note = (int)destinationNote; |
|
|
|
|
slideActive = false; |
|
|
|
|
currentNote = (double)destinationNote; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return currentNote; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SynthDevice::clearEvents() |
|
|
|
|