45 |
Voice::Voice() { |
Voice::Voice() { |
46 |
pEngine = NULL; |
pEngine = NULL; |
47 |
pDiskThread = NULL; |
pDiskThread = NULL; |
48 |
Active = false; |
PlaybackState = playback_state_end; |
49 |
pEG1 = NULL; |
pEG1 = NULL; |
50 |
pEG2 = NULL; |
pEG2 = NULL; |
51 |
pEG3 = NULL; |
pEG3 = NULL; |
108 |
* @param pInstrument - points to the loaded instrument which provides sample wave(s) and articulation data |
* @param pInstrument - points to the loaded instrument which provides sample wave(s) and articulation data |
109 |
* @param iLayer - layer number this voice refers to (only if this is a layered sound of course) |
* @param iLayer - layer number this voice refers to (only if this is a layered sound of course) |
110 |
* @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false) |
* @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false) |
111 |
|
* @param VoiceStealing - wether the voice is allowed to steal voices for further subvoices |
112 |
* @returns 0 on success, a value < 0 if something failed |
* @returns 0 on success, a value < 0 if something failed |
113 |
*/ |
*/ |
114 |
int Voice::Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice) { |
int Voice::Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) { |
115 |
if (!pInstrument) { |
if (!pInstrument) { |
116 |
dmsg(1,("voice::trigger: !pInstrument\n")); |
dmsg(1,("voice::trigger: !pInstrument\n")); |
117 |
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
118 |
} |
} |
119 |
|
|
120 |
Type = type_normal; |
Type = type_normal; |
|
Active = true; |
|
121 |
MIDIKey = itNoteOnEvent->Param.Note.Key; |
MIDIKey = itNoteOnEvent->Param.Note.Key; |
122 |
pRegion = pInstrument->GetRegion(MIDIKey); |
pRegion = pInstrument->GetRegion(MIDIKey); |
123 |
PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed |
PlaybackState = playback_state_ram; // we always start playback from RAM cache and switch then to disk if needed |
124 |
Delay = itNoteOnEvent->FragmentPos(); |
Delay = itNoteOnEvent->FragmentPos(); |
125 |
itTriggerEvent = itNoteOnEvent; |
itTriggerEvent = itNoteOnEvent; |
126 |
itKillEvent = Pool<Event>::Iterator(); |
itKillEvent = Pool<Event>::Iterator(); |
127 |
|
itChildVoice = Pool<Voice>::Iterator(); |
128 |
|
|
129 |
if (!pRegion) { |
if (!pRegion) { |
130 |
std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush; |
std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush; |
147 |
// if this is the 1st layer then spawn further voices for all the other layers |
// if this is the 1st layer then spawn further voices for all the other layers |
148 |
if (iLayer == 0) |
if (iLayer == 0) |
149 |
for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++) |
for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++) |
150 |
pEngine->LaunchVoice(itNoteOnEvent, iNewLayer, ReleaseTriggerVoice); |
itChildVoice = pEngine->LaunchVoice(itNoteOnEvent, iNewLayer, ReleaseTriggerVoice, VoiceStealing); |
151 |
break; |
break; |
152 |
case ::gig::dimension_velocity: |
case ::gig::dimension_velocity: |
153 |
DimValues[i] = itNoteOnEvent->Param.Note.Velocity; |
DimValues[i] = itNoteOnEvent->Param.Note.Velocity; |
702 |
break; |
break; |
703 |
|
|
704 |
case playback_state_end: |
case playback_state_end: |
705 |
KillImmediately(); // free voice |
std::cerr << "gig::Voice::Render(): entered with playback_state_end, this is a bug!\n" << std::flush; |
706 |
break; |
break; |
707 |
} |
} |
708 |
|
|
719 |
|
|
720 |
itTriggerEvent = Pool<Event>::Iterator(); |
itTriggerEvent = Pool<Event>::Iterator(); |
721 |
|
|
722 |
// If release stage finished, let the voice be killed |
// If sample stream or release stage finished, kill the voice |
723 |
if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end; |
if (PlaybackState == playback_state_end || pEG1->GetStage() == EGADSR::stage_end) KillImmediately(); |
724 |
} |
} |
725 |
|
|
726 |
/** |
/** |
735 |
DiskStreamRef.hStream = 0; |
DiskStreamRef.hStream = 0; |
736 |
DiskStreamRef.State = Stream::state_unused; |
DiskStreamRef.State = Stream::state_unused; |
737 |
DiskStreamRef.OrderID = 0; |
DiskStreamRef.OrderID = 0; |
738 |
Active = false; |
PlaybackState = playback_state_end; |
739 |
|
itTriggerEvent = Pool<Event>::Iterator(); |
740 |
|
itKillEvent = Pool<Event>::Iterator(); |
741 |
} |
} |
742 |
|
|
743 |
/** |
/** |
1057 |
* @param itKillEvent - event which caused the voice to be killed |
* @param itKillEvent - event which caused the voice to be killed |
1058 |
*/ |
*/ |
1059 |
void Voice::Kill(Pool<Event>::Iterator& itKillEvent) { |
void Voice::Kill(Pool<Event>::Iterator& itKillEvent) { |
1060 |
|
//FIXME: just two sanity checks for debugging, can be removed |
1061 |
|
if (!itKillEvent) dmsg(1,("gig::Voice::Kill(): ERROR, !itKillEvent !!!\n")); |
1062 |
|
if (itKillEvent && !itKillEvent.isValid()) dmsg(1,("gig::Voice::Kill(): ERROR, itKillEvent invalid !!!\n")); |
1063 |
|
|
1064 |
if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return; |
if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return; |
1065 |
this->itKillEvent = itKillEvent; |
this->itKillEvent = itKillEvent; |
1066 |
} |
} |