--- linuxsampler/trunk/src/engines/gig/Voice.cpp 2005/01/03 02:48:25 335 +++ linuxsampler/trunk/src/engines/gig/Voice.cpp 2005/03/05 07:27:48 425 @@ -3,6 +3,7 @@ * LinuxSampler - modular, streaming capable sampler * * * * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * + * Copyright (C) 2005 Christian Schoenebeck * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -58,11 +59,17 @@ pLFO2 = NULL; pLFO3 = NULL; KeyGroup = 0; - SynthesisMode = 0; //Set all mode bits to 0 first - + SynthesisMode = 0; // set all mode bits to 0 first // select synthesis implementation (currently either pure C++ or MMX+SSE(1)) + #if ARCH_X86 SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, Features::supportsMMX() && Features::supportsSSE()); + #else + SYNTHESIS_MODE_SET_IMPLEMENTATION(SynthesisMode, false); + #endif SYNTHESIS_MODE_SET_PROFILING(SynthesisMode, true); + + FilterLeft.Reset(); + FilterRight.Reset(); } Voice::~Voice() { @@ -110,15 +117,19 @@ * Initializes and triggers the voice, a disk stream will be launched if * needed. * + * @param pEngineChannel - engine channel on which this voice was ordered * @param itNoteOnEvent - event that caused triggering of this voice * @param PitchBend - MIDI detune factor (-8192 ... +8191) * @param pInstrument - points to the loaded instrument which provides sample wave(s) and articulation data * @param iLayer - layer number this voice refers to (only if this is a layered sound of course) * @param ReleaseTriggerVoice - if this new voice is a release trigger voice (optional, default = false) * @param VoiceStealing - wether the voice is allowed to steal voices for further subvoices - * @returns 0 on success, a value < 0 if something failed + * @returns 0 on success, a value < 0 if the voice wasn't triggered + * (either due to an error or e.g. because no region is + * defined for the given key) */ - int Voice::Trigger(Pool::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) { + int Voice::Trigger(EngineChannel* pEngineChannel, Pool::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice, bool VoiceStealing) { + this->pEngineChannel = pEngineChannel; if (!pInstrument) { dmsg(1,("voice::trigger: !pInstrument\n")); exit(EXIT_FAILURE); @@ -137,8 +148,7 @@ itChildVoice = Pool::Iterator(); if (!pRegion) { - std::cerr << "gig::Voice: No Region defined for MIDI key " << MIDIKey << std::endl << std::flush; - KillImmediately(); + dmsg(4, ("gig::Voice: No Region defined for MIDI key %d\n", MIDIKey)); return -1; } @@ -146,7 +156,7 @@ // get current dimension values to select the right dimension region //FIXME: controller values for selecting the dimension region here are currently not sample accurate - uint DimValues[5] = {0,0,0,0,0}; + uint DimValues[8] = { 0 }; for (int i = pRegion->Dimensions - 1; i >= 0; i--) { switch (pRegion->pDimensionDefinitions[i].dimension) { case ::gig::dimension_samplechannel: @@ -157,7 +167,7 @@ // if this is the 1st layer then spawn further voices for all the other layers if (iLayer == 0) for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++) - itChildVoice = pEngine->LaunchVoice(itNoteOnEvent, iNewLayer, ReleaseTriggerVoice, VoiceStealing); + itChildVoice = pEngine->LaunchVoice(pEngineChannel, itNoteOnEvent, iNewLayer, ReleaseTriggerVoice, VoiceStealing); break; case ::gig::dimension_velocity: DimValues[i] = itNoteOnEvent->Param.Note.Velocity; @@ -170,76 +180,76 @@ DimValues[i] = (uint) ReleaseTriggerVoice; break; case ::gig::dimension_keyboard: - DimValues[i] = (uint) itNoteOnEvent->Param.Note.Key; + DimValues[i] = (uint) pEngineChannel->CurrentKeyDimension; break; case ::gig::dimension_modwheel: - DimValues[i] = pEngine->ControllerTable[1]; + DimValues[i] = pEngineChannel->ControllerTable[1]; break; case ::gig::dimension_breath: - DimValues[i] = pEngine->ControllerTable[2]; + DimValues[i] = pEngineChannel->ControllerTable[2]; break; case ::gig::dimension_foot: - DimValues[i] = pEngine->ControllerTable[4]; + DimValues[i] = pEngineChannel->ControllerTable[4]; break; case ::gig::dimension_portamentotime: - DimValues[i] = pEngine->ControllerTable[5]; + DimValues[i] = pEngineChannel->ControllerTable[5]; break; case ::gig::dimension_effect1: - DimValues[i] = pEngine->ControllerTable[12]; + DimValues[i] = pEngineChannel->ControllerTable[12]; break; case ::gig::dimension_effect2: - DimValues[i] = pEngine->ControllerTable[13]; + DimValues[i] = pEngineChannel->ControllerTable[13]; break; case ::gig::dimension_genpurpose1: - DimValues[i] = pEngine->ControllerTable[16]; + DimValues[i] = pEngineChannel->ControllerTable[16]; break; case ::gig::dimension_genpurpose2: - DimValues[i] = pEngine->ControllerTable[17]; + DimValues[i] = pEngineChannel->ControllerTable[17]; break; case ::gig::dimension_genpurpose3: - DimValues[i] = pEngine->ControllerTable[18]; + DimValues[i] = pEngineChannel->ControllerTable[18]; break; case ::gig::dimension_genpurpose4: - DimValues[i] = pEngine->ControllerTable[19]; + DimValues[i] = pEngineChannel->ControllerTable[19]; break; case ::gig::dimension_sustainpedal: - DimValues[i] = pEngine->ControllerTable[64]; + DimValues[i] = pEngineChannel->ControllerTable[64]; break; case ::gig::dimension_portamento: - DimValues[i] = pEngine->ControllerTable[65]; + DimValues[i] = pEngineChannel->ControllerTable[65]; break; case ::gig::dimension_sostenutopedal: - DimValues[i] = pEngine->ControllerTable[66]; + DimValues[i] = pEngineChannel->ControllerTable[66]; break; case ::gig::dimension_softpedal: - DimValues[i] = pEngine->ControllerTable[67]; + DimValues[i] = pEngineChannel->ControllerTable[67]; break; case ::gig::dimension_genpurpose5: - DimValues[i] = pEngine->ControllerTable[80]; + DimValues[i] = pEngineChannel->ControllerTable[80]; break; case ::gig::dimension_genpurpose6: - DimValues[i] = pEngine->ControllerTable[81]; + DimValues[i] = pEngineChannel->ControllerTable[81]; break; case ::gig::dimension_genpurpose7: - DimValues[i] = pEngine->ControllerTable[82]; + DimValues[i] = pEngineChannel->ControllerTable[82]; break; case ::gig::dimension_genpurpose8: - DimValues[i] = pEngine->ControllerTable[83]; + DimValues[i] = pEngineChannel->ControllerTable[83]; break; case ::gig::dimension_effect1depth: - DimValues[i] = pEngine->ControllerTable[91]; + DimValues[i] = pEngineChannel->ControllerTable[91]; break; case ::gig::dimension_effect2depth: - DimValues[i] = pEngine->ControllerTable[92]; + DimValues[i] = pEngineChannel->ControllerTable[92]; break; case ::gig::dimension_effect3depth: - DimValues[i] = pEngine->ControllerTable[93]; + DimValues[i] = pEngineChannel->ControllerTable[93]; break; case ::gig::dimension_effect4depth: - DimValues[i] = pEngine->ControllerTable[94]; + DimValues[i] = pEngineChannel->ControllerTable[94]; break; case ::gig::dimension_effect5depth: - DimValues[i] = pEngine->ControllerTable[95]; + DimValues[i] = pEngineChannel->ControllerTable[95]; break; case ::gig::dimension_none: std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush; @@ -248,9 +258,10 @@ std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush; } } - pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]); + pDimRgn = pRegion->GetDimensionRegionByValue(DimValues); pSample = pDimRgn->pSample; // sample won't change until the voice is finished + if (!pSample || !pSample->SamplesTotal) return -1; // no need to continue if sample is silent // select channel mode (mono or stereo) SYNTHESIS_MODE_SET_CHANNELS(SynthesisMode, pSample->Channels == 2); @@ -264,7 +275,7 @@ CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity); break; case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate - CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]); + CrossfadeVolume = CrossfadeAttenuation(pEngineChannel->ControllerTable[pDimRgn->AttenuationController.controller_number]); break; case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined default: @@ -318,6 +329,8 @@ Volume = pDimRgn->GetVelocityAttenuation(itNoteOnEvent->Param.Note.Velocity) / 32768.0f; // we downscale by 32768 to convert from int16 value range to DSP value range (which is -1.0..1.0) + Volume *= pDimRgn->SampleAttenuation; + // setup EG 1 (VCA EG) { // get current value of EG1 controller @@ -333,7 +346,7 @@ eg1controllervalue = itNoteOnEvent->Param.Note.Velocity; break; case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller - eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number]; + eg1controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG1Controller.controller_number]; break; } if (pDimRgn->EG1ControllerInvert) eg1controllervalue = 127 - eg1controllervalue; @@ -352,7 +365,10 @@ pDimRgn->EG1InfiniteSustain, pDimRgn->EG1Sustain, pDimRgn->EG1Release + eg1release, - Delay); + // the SSE synthesis implementation requires + // the vca start to be 16 byte aligned + SYNTHESIS_MODE_GET_IMPLEMENTATION(SynthesisMode) ? + Delay & 0xfffffffc : Delay); } @@ -371,7 +387,7 @@ eg2controllervalue = itNoteOnEvent->Param.Note.Velocity; break; case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller - eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number]; + eg2controllervalue = pEngineChannel->ControllerTable[pDimRgn->EG2Controller.controller_number]; break; } if (pDimRgn->EG2ControllerInvert) eg2controllervalue = 127 - eg2controllervalue; @@ -432,7 +448,7 @@ pLFO1->Trigger(pDimRgn->LFO1Frequency, lfo1_internal_depth, pDimRgn->LFO1ControlDepth, - pEngine->ControllerTable[pLFO1->ExtController], + pEngineChannel->ControllerTable[pLFO1->ExtController], pDimRgn->LFO1FlipPhase, pEngine->SampleRate, Delay); @@ -470,7 +486,7 @@ pLFO2->Trigger(pDimRgn->LFO2Frequency, lfo2_internal_depth, pDimRgn->LFO2ControlDepth, - pEngine->ControllerTable[pLFO2->ExtController], + pEngineChannel->ControllerTable[pLFO2->ExtController], pDimRgn->LFO2FlipPhase, pEngine->SampleRate, Delay); @@ -508,7 +524,7 @@ pLFO3->Trigger(pDimRgn->LFO3Frequency, lfo3_internal_depth, pDimRgn->LFO3ControlDepth, - pEngine->ControllerTable[pLFO3->ExtController], + pEngineChannel->ControllerTable[pLFO3->ExtController], false, pEngine->SampleRate, Delay); @@ -516,11 +532,12 @@ #if FORCE_FILTER_USAGE - SYNTHESIS_MODE_SET_FILTER(SynthesisMode, true); + const bool bUseFilter = true; #else // use filter only if instrument file told so - SYNTHESIS_MODE_SET_FILTER(SynthesisMode, pDimRgn->VCFEnabled); + const bool bUseFilter = pDimRgn->VCFEnabled; #endif // FORCE_FILTER_USAGE - if (pDimRgn->VCFEnabled) { + SYNTHESIS_MODE_SET_FILTER(SynthesisMode, bUseFilter); + if (bUseFilter) { #ifdef OVERRIDE_FILTER_CUTOFF_CTRL VCFCutoffCtrl.controller = OVERRIDE_FILTER_CUTOFF_CTRL; #else // use the one defined in the instrument file @@ -590,8 +607,8 @@ FilterRight.SetType(OVERRIDE_FILTER_TYPE); #endif // OVERRIDE_FILTER_TYPE - VCFCutoffCtrl.value = pEngine->ControllerTable[VCFCutoffCtrl.controller]; - VCFResonanceCtrl.value = pEngine->ControllerTable[VCFResonanceCtrl.controller]; + VCFCutoffCtrl.value = pEngineChannel->ControllerTable[VCFCutoffCtrl.controller]; + VCFResonanceCtrl.value = pEngineChannel->ControllerTable[VCFResonanceCtrl.controller]; // calculate cutoff frequency float cutoff = (!VCFCutoffCtrl.controller) @@ -638,7 +655,7 @@ // Reset the synthesis parameter matrix - pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume); + pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngineChannel->GlobalVolume); pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase); pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue); pEngine->ResetSynthesisParameters(Event::destination_vcfr, VCFResonanceCtrl.fvalue); @@ -647,8 +664,8 @@ ProcessEvents(Samples); // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment - pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent); - pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend); + pEG1->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent); + pEG2->Process(Samples, pEngineChannel->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend); if (pEG3->Process(Samples)) { // if pitch EG is active SYNTHESIS_MODE_SET_INTERPOLATE(SynthesisMode, true); SYNTHESIS_MODE_SET_CONSTPITCH(SynthesisMode, false); @@ -661,7 +678,7 @@ } if (SYNTHESIS_MODE_GET_FILTER(SynthesisMode)) - CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters + CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters switch (this->PlaybackState) { @@ -862,7 +879,7 @@ crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value); - float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume; + float effective_volume = crossfadevolume * this->Volume * pEngineChannel->GlobalVolume; // apply volume value to the volume parameter sequence for (uint i = itVCAEvent->FragmentPos(); i < end; i++) { @@ -942,8 +959,8 @@ biquad_param_t bqmain; float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0]; float prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][0]; - FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate); - FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate); + FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate); + FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate); pEngine->pBasicFilterParameters[0] = bqbase; pEngine->pMainFilterParameters[0] = bqmain; @@ -956,8 +973,8 @@ { prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i]; prev_res = pEngine->pSynthesisParameters[Event::destination_vcfr][i]; - FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate); - FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate); + FilterLeft.SetParameters( &bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate); + FilterRight.SetParameters(&bqbase, &bqmain, prev_cutoff + FILTER_CUTOFF_MIN, prev_res, pEngine->SampleRate); } }