/[svn]/linuxsampler/trunk/src/engines/gig/Voice.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/gig/Voice.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 56 by schoenebeck, Tue Apr 27 09:21:58 2004 UTC revision 271 by schoenebeck, Fri Oct 8 20:51:39 2004 UTC
# Line 27  Line 27 
27    
28  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
29    
     // FIXME: no support for layers (nor crossfades) yet  
   
30      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());      const float Voice::FILTER_CUTOFF_COEFF(CalculateFilterCutoffCoeff());
31    
32        const int Voice::FILTER_UPDATE_MASK(CalculateFilterUpdateMask());
33    
34      float Voice::CalculateFilterCutoffCoeff() {      float Voice::CalculateFilterCutoffCoeff() {
35          return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);          return log(FILTER_CUTOFF_MIN / FILTER_CUTOFF_MAX);
36      }      }
37    
38        int Voice::CalculateFilterUpdateMask() {
39            if (FILTER_UPDATE_PERIOD <= 0) return 0;
40            int power_of_two;
41            for (power_of_two = 0; 1<<power_of_two < FILTER_UPDATE_PERIOD; power_of_two++);
42            return (1 << power_of_two) - 1;
43        }
44    
45      Voice::Voice() {      Voice::Voice() {
46          pEngine     = NULL;          pEngine     = NULL;
47          pDiskThread = NULL;          pDiskThread = NULL;
# Line 48  namespace LinuxSampler { namespace gig { Line 55  namespace LinuxSampler { namespace gig {
55          pLFO1  = NULL;          pLFO1  = NULL;
56          pLFO2  = NULL;          pLFO2  = NULL;
57          pLFO3  = NULL;          pLFO3  = NULL;
58            KeyGroup = 0;
59      }      }
60    
61      Voice::~Voice() {      Voice::~Voice() {
# Line 62  namespace LinuxSampler { namespace gig { Line 70  namespace LinuxSampler { namespace gig {
70          if (pVCOManipulator)  delete pVCOManipulator;          if (pVCOManipulator)  delete pVCOManipulator;
71      }      }
72    
     void Voice::SetOutput(AudioOutputDevice* pAudioOutputDevice) {  
         this->pOutputLeft        = pAudioOutputDevice->Channel(0)->Buffer();  
         this->pOutputRight       = pAudioOutputDevice->Channel(1)->Buffer();  
         this->MaxSamplesPerCycle = pAudioOutputDevice->MaxSamplesPerCycle();  
         this->SampleRate         = pAudioOutputDevice->SampleRate();  
     }  
   
73      void Voice::SetEngine(Engine* pEngine) {      void Voice::SetEngine(Engine* pEngine) {
74          this->pEngine = pEngine;          this->pEngine = pEngine;
75    
# Line 95  namespace LinuxSampler { namespace gig { Line 96  namespace LinuxSampler { namespace gig {
96          pLFO3  = new LFO<gig::VCOManipulator>(-1200.0f, 1200.0f, LFO<VCOManipulator>::propagation_middle_balanced, pVCOManipulator, pEngine->pEventPool); // +-1 octave (+-1200 cents) max.          pLFO3  = new LFO<gig::VCOManipulator>(-1200.0f, 1200.0f, LFO<VCOManipulator>::propagation_middle_balanced, pVCOManipulator, pEngine->pEventPool); // +-1 octave (+-1200 cents) max.
97    
98          this->pDiskThread = pEngine->pDiskThread;          this->pDiskThread = pEngine->pDiskThread;
99          dmsg(1,("Voice::SetEngine()\n"));          dmsg(6,("Voice::SetEngine()\n"));
100      }      }
101    
102      /**      /**
103       *  Initializes and triggers the voice, a disk stream will be launched if       *  Initializes and triggers the voice, a disk stream will be launched if
104       *  needed.       *  needed.
105       *       *
106       *  @param pNoteOnEvent - event that caused triggering of this voice       *  @param itNoteOnEvent       - event that caused triggering of this voice
107       *  @param PitchBend    - MIDI detune factor (-8192 ... +8191)       *  @param PitchBend           - MIDI detune factor (-8192 ... +8191)
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       *  @returns            0 on success, a value < 0 if something failed       *  @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)
111         *  @returns 0 on success, a value < 0 if something failed
112       */       */
113      int Voice::Trigger(Event* pNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument) {      int Voice::Trigger(Pool<Event>::Iterator& itNoteOnEvent, int PitchBend, ::gig::Instrument* pInstrument, int iLayer, bool ReleaseTriggerVoice) {
114          if (!pInstrument) {          if (!pInstrument) {
115             dmsg(1,("voice::trigger: !pInstrument\n"));             dmsg(1,("voice::trigger: !pInstrument\n"));
116             exit(EXIT_FAILURE);             exit(EXIT_FAILURE);
117          }          }
118    
119            Type            = type_normal;
120          Active          = true;          Active          = true;
121          MIDIKey         = pNoteOnEvent->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          Pos             = 0;          Delay           = itNoteOnEvent->FragmentPos();
125          Delay           = pNoteOnEvent->FragmentPos();          itTriggerEvent  = itNoteOnEvent;
126          pTriggerEvent   = pNoteOnEvent;          itKillEvent     = Pool<Event>::Iterator();
127    
128          if (!pRegion) {          if (!pRegion) {
129              std::cerr << "Audio Thread: 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;
130              Kill();              KillImmediately();
131              return -1;              return -1;
132          }          }
133    
134          //TODO: current MIDI controller values are not taken into account yet          KeyGroup = pRegion->KeyGroup;
135          ::gig::DimensionRegion* pDimRgn = NULL;  
136          for (int i = pRegion->Dimensions - 1; i >= 0; i--) { // Check if instrument has a velocity split          // get current dimension values to select the right dimension region
137              if (pRegion->pDimensionDefinitions[i].dimension == ::gig::dimension_velocity) {          //FIXME: controller values for selecting the dimension region here are currently not sample accurate
138                  uint DimValues[5] = {0,0,0,0,0};          uint DimValues[5] = {0,0,0,0,0};
139                      DimValues[i] = pNoteOnEvent->Velocity;          for (int i = pRegion->Dimensions - 1; i >= 0; i--) {
140                  pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);              switch (pRegion->pDimensionDefinitions[i].dimension) {
141                  break;                  case ::gig::dimension_samplechannel:
142                        DimValues[i] = 0; //TODO: we currently ignore this dimension
143                        break;
144                    case ::gig::dimension_layer:
145                        DimValues[i] = iLayer;
146                        // if this is the 1st layer then spawn further voices for all the other layers
147                        if (iLayer == 0)
148                            for (int iNewLayer = 1; iNewLayer < pRegion->pDimensionDefinitions[i].zones; iNewLayer++)
149                                pEngine->LaunchVoice(itNoteOnEvent, iNewLayer, ReleaseTriggerVoice);
150                        break;
151                    case ::gig::dimension_velocity:
152                        DimValues[i] = itNoteOnEvent->Param.Note.Velocity;
153                        break;
154                    case ::gig::dimension_channelaftertouch:
155                        DimValues[i] = 0; //TODO: we currently ignore this dimension
156                        break;
157                    case ::gig::dimension_releasetrigger:
158                        Type = (ReleaseTriggerVoice) ? type_release_trigger : (!iLayer) ? type_release_trigger_required : type_normal;
159                        DimValues[i] = (uint) ReleaseTriggerVoice;
160                        break;
161                    case ::gig::dimension_keyboard:
162                        DimValues[i] = (uint) itNoteOnEvent->Param.Note.Key;
163                        break;
164                    case ::gig::dimension_modwheel:
165                        DimValues[i] = pEngine->ControllerTable[1];
166                        break;
167                    case ::gig::dimension_breath:
168                        DimValues[i] = pEngine->ControllerTable[2];
169                        break;
170                    case ::gig::dimension_foot:
171                        DimValues[i] = pEngine->ControllerTable[4];
172                        break;
173                    case ::gig::dimension_portamentotime:
174                        DimValues[i] = pEngine->ControllerTable[5];
175                        break;
176                    case ::gig::dimension_effect1:
177                        DimValues[i] = pEngine->ControllerTable[12];
178                        break;
179                    case ::gig::dimension_effect2:
180                        DimValues[i] = pEngine->ControllerTable[13];
181                        break;
182                    case ::gig::dimension_genpurpose1:
183                        DimValues[i] = pEngine->ControllerTable[16];
184                        break;
185                    case ::gig::dimension_genpurpose2:
186                        DimValues[i] = pEngine->ControllerTable[17];
187                        break;
188                    case ::gig::dimension_genpurpose3:
189                        DimValues[i] = pEngine->ControllerTable[18];
190                        break;
191                    case ::gig::dimension_genpurpose4:
192                        DimValues[i] = pEngine->ControllerTable[19];
193                        break;
194                    case ::gig::dimension_sustainpedal:
195                        DimValues[i] = pEngine->ControllerTable[64];
196                        break;
197                    case ::gig::dimension_portamento:
198                        DimValues[i] = pEngine->ControllerTable[65];
199                        break;
200                    case ::gig::dimension_sostenutopedal:
201                        DimValues[i] = pEngine->ControllerTable[66];
202                        break;
203                    case ::gig::dimension_softpedal:
204                        DimValues[i] = pEngine->ControllerTable[67];
205                        break;
206                    case ::gig::dimension_genpurpose5:
207                        DimValues[i] = pEngine->ControllerTable[80];
208                        break;
209                    case ::gig::dimension_genpurpose6:
210                        DimValues[i] = pEngine->ControllerTable[81];
211                        break;
212                    case ::gig::dimension_genpurpose7:
213                        DimValues[i] = pEngine->ControllerTable[82];
214                        break;
215                    case ::gig::dimension_genpurpose8:
216                        DimValues[i] = pEngine->ControllerTable[83];
217                        break;
218                    case ::gig::dimension_effect1depth:
219                        DimValues[i] = pEngine->ControllerTable[91];
220                        break;
221                    case ::gig::dimension_effect2depth:
222                        DimValues[i] = pEngine->ControllerTable[92];
223                        break;
224                    case ::gig::dimension_effect3depth:
225                        DimValues[i] = pEngine->ControllerTable[93];
226                        break;
227                    case ::gig::dimension_effect4depth:
228                        DimValues[i] = pEngine->ControllerTable[94];
229                        break;
230                    case ::gig::dimension_effect5depth:
231                        DimValues[i] = pEngine->ControllerTable[95];
232                        break;
233                    case ::gig::dimension_none:
234                        std::cerr << "gig::Voice::Trigger() Error: dimension=none\n" << std::flush;
235                        break;
236                    default:
237                        std::cerr << "gig::Voice::Trigger() Error: Unknown dimension\n" << std::flush;
238              }              }
239          }          }
240          if (!pDimRgn) { // if there was no velocity split          pDimRgn = pRegion->GetDimensionRegionByValue(DimValues[4],DimValues[3],DimValues[2],DimValues[1],DimValues[0]);
241              pDimRgn = pRegion->GetDimensionRegionByValue(0,0,0,0,0);  
242            // get starting crossfade volume level
243            switch (pDimRgn->AttenuationController.type) {
244                case ::gig::attenuation_ctrl_t::type_channelaftertouch:
245                    CrossfadeVolume = 1.0f; //TODO: aftertouch not supported yet
246                    break;
247                case ::gig::attenuation_ctrl_t::type_velocity:
248                    CrossfadeVolume = CrossfadeAttenuation(itNoteOnEvent->Param.Note.Velocity);
249                    break;
250                case ::gig::attenuation_ctrl_t::type_controlchange: //FIXME: currently not sample accurate
251                    CrossfadeVolume = CrossfadeAttenuation(pEngine->ControllerTable[pDimRgn->AttenuationController.controller_number]);
252                    break;
253                case ::gig::attenuation_ctrl_t::type_none: // no crossfade defined
254                default:
255                    CrossfadeVolume = 1.0f;
256          }          }
257    
258            PanLeft  = 1.0f - float(RTMath::Max(pDimRgn->Pan, 0)) /  63.0f;
259            PanRight = 1.0f - float(RTMath::Min(pDimRgn->Pan, 0)) / -64.0f;
260    
261          pSample = pDimRgn->pSample; // sample won't change until the voice is finished          pSample = pDimRgn->pSample; // sample won't change until the voice is finished
262    
263            Pos = pDimRgn->SampleStartOffset; // offset where we should start playback of sample (0 - 2000 sample points)
264    
265          // Check if the sample needs disk streaming or is too short for that          // Check if the sample needs disk streaming or is too short for that
266          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;          long cachedsamples = pSample->GetCache().Size / pSample->FrameSize;
267          DiskVoice          = cachedsamples < pSample->SamplesTotal;          DiskVoice          = cachedsamples < pSample->SamplesTotal;
268    
269          if (DiskVoice) { // voice to be streamed from disk          if (DiskVoice) { // voice to be streamed from disk
270              MaxRAMPos = cachedsamples - (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK)              MaxRAMPos = cachedsamples - (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels; //TODO: this calculation is too pessimistic and may better be moved to Render() method, so it calculates MaxRAMPos dependent to the current demand of sample points to be rendered (e.g. in case of JACK)
271    
272              // check if there's a loop defined which completely fits into the cached (RAM) part of the sample              // check if there's a loop defined which completely fits into the cached (RAM) part of the sample
273              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {              if (pSample->Loops && pSample->LoopEnd <= MaxRAMPos) {
# Line 159  namespace LinuxSampler { namespace gig { Line 278  namespace LinuxSampler { namespace gig {
278    
279              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {              if (pDiskThread->OrderNewStream(&DiskStreamRef, pSample, MaxRAMPos, !RAMLoop) < 0) {
280                  dmsg(1,("Disk stream order failed!\n"));                  dmsg(1,("Disk stream order failed!\n"));
281                  Kill();                  KillImmediately();
282                  return -1;                  return -1;
283              }              }
284              dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));              dmsg(4,("Disk voice launched (cached samples: %d, total Samples: %d, MaxRAMPos: %d, RAMLooping: %s)\n", cachedsamples, pSample->SamplesTotal, MaxRAMPos, (RAMLoop) ? "yes" : "no"));
# Line 177  namespace LinuxSampler { namespace gig { Line 296  namespace LinuxSampler { namespace gig {
296    
297          // calculate initial pitch value          // calculate initial pitch value
298          {          {
299              double pitchbasecents = pDimRgn->FineTune * 10;              double pitchbasecents = pDimRgn->FineTune * 10 + (int) pEngine->ScaleTuning[MIDIKey % 12];
300              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;              if (pDimRgn->PitchTrack) pitchbasecents += (MIDIKey - (int) pDimRgn->UnityNote) * 100;
301              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents);              this->PitchBase = RTMath::CentsToFreqRatio(pitchbasecents) * (double(pSample->SamplesPerSecond) / double(pEngine->pAudioOutputDevice->SampleRate()));
302              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents              this->PitchBend = RTMath::CentsToFreqRatio(((double) PitchBend / 8192.0) * 200.0); // pitchbend wheel +-2 semitones = 200 cents
303          }          }
304    
305    
306          Volume = pDimRgn->GetVelocityAttenuation(pNoteOnEvent->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->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)
307    
308    
309          // setup EG 1 (VCA EG)          // setup EG 1 (VCA EG)
# Line 199  namespace LinuxSampler { namespace gig { Line 318  namespace LinuxSampler { namespace gig {
318                      eg1controllervalue = 0; // TODO: aftertouch not yet supported                      eg1controllervalue = 0; // TODO: aftertouch not yet supported
319                      break;                      break;
320                  case ::gig::eg1_ctrl_t::type_velocity:                  case ::gig::eg1_ctrl_t::type_velocity:
321                      eg1controllervalue = pNoteOnEvent->Velocity;                      eg1controllervalue = itNoteOnEvent->Param.Note.Velocity;
322                      break;                      break;
323                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg1_ctrl_t::type_controlchange: // MIDI control change controller
324                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];                      eg1controllervalue = pEngine->ControllerTable[pDimRgn->EG1Controller.controller_number];
# Line 238  namespace LinuxSampler { namespace gig { Line 357  namespace LinuxSampler { namespace gig {
357                      eg2controllervalue = 0; // TODO: aftertouch not yet supported                      eg2controllervalue = 0; // TODO: aftertouch not yet supported
358                      break;                      break;
359                  case ::gig::eg2_ctrl_t::type_velocity:                  case ::gig::eg2_ctrl_t::type_velocity:
360                      eg2controllervalue = pNoteOnEvent->Velocity;                      eg2controllervalue = itNoteOnEvent->Param.Note.Velocity;
361                      break;                      break;
362                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller                  case ::gig::eg2_ctrl_t::type_controlchange: // MIDI control change controller
363                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];                      eg2controllervalue = pEngine->ControllerTable[pDimRgn->EG2Controller.controller_number];
# Line 305  namespace LinuxSampler { namespace gig { Line 424  namespace LinuxSampler { namespace gig {
424                            pDimRgn->LFO1ControlDepth,                            pDimRgn->LFO1ControlDepth,
425                            pEngine->ControllerTable[pLFO1->ExtController],                            pEngine->ControllerTable[pLFO1->ExtController],
426                            pDimRgn->LFO1FlipPhase,                            pDimRgn->LFO1FlipPhase,
427                            this->SampleRate,                            pEngine->SampleRate,
428                            Delay);                            Delay);
429          }          }
430    
# Line 343  namespace LinuxSampler { namespace gig { Line 462  namespace LinuxSampler { namespace gig {
462                            pDimRgn->LFO2ControlDepth,                            pDimRgn->LFO2ControlDepth,
463                            pEngine->ControllerTable[pLFO2->ExtController],                            pEngine->ControllerTable[pLFO2->ExtController],
464                            pDimRgn->LFO2FlipPhase,                            pDimRgn->LFO2FlipPhase,
465                              pEngine->SampleRate,
466                            Delay);                            Delay);
467          }          }
468      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
# Line 380  namespace LinuxSampler { namespace gig { Line 500  namespace LinuxSampler { namespace gig {
500                            pDimRgn->LFO3ControlDepth,                            pDimRgn->LFO3ControlDepth,
501                            pEngine->ControllerTable[pLFO3->ExtController],                            pEngine->ControllerTable[pLFO3->ExtController],
502                            false,                            false,
503                            this->SampleRate,                            pEngine->SampleRate,
504                            Delay);                            Delay);
505          }          }
506    
# Line 465  namespace LinuxSampler { namespace gig { Line 585  namespace LinuxSampler { namespace gig {
585    
586              // calculate cutoff frequency              // calculate cutoff frequency
587              float cutoff = (!VCFCutoffCtrl.controller)              float cutoff = (!VCFCutoffCtrl.controller)
588                  ? exp((float) (127 - pNoteOnEvent->Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX                  ? exp((float) (127 - itNoteOnEvent->Param.Note.Velocity) * (float) pDimRgn->VCFVelocityScale * 6.2E-5f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX
589                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;                  : exp((float) VCFCutoffCtrl.value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX;
590    
591              // calculate resonance              // calculate resonance
592              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0              float resonance = (float) VCFResonanceCtrl.value * 0.00787f;   // 0.0..1.0
593              if (pDimRgn->VCFKeyboardTracking) {              if (pDimRgn->VCFKeyboardTracking) {
594                  resonance += (float) (pNoteOnEvent->Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;                  resonance += (float) (itNoteOnEvent->Param.Note.Key - pDimRgn->VCFKeyboardTrackingBreakpoint) * 0.00787f;
595              }              }
596              Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)              Constrain(resonance, 0.0, 1.0); // correct resonance if outside allowed value range (0.0..1.0)
597    
598              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;              VCFCutoffCtrl.fvalue    = cutoff - FILTER_CUTOFF_MIN;
599              VCFResonanceCtrl.fvalue = resonance;              VCFResonanceCtrl.fvalue = resonance;
600    
601              FilterLeft.SetParameters(cutoff,  resonance, SampleRate);              FilterLeft.SetParameters(cutoff,  resonance, pEngine->SampleRate);
602              FilterRight.SetParameters(cutoff, resonance, SampleRate);              FilterRight.SetParameters(cutoff, resonance, pEngine->SampleRate);
603    
604              FilterUpdateCounter = -1;              FilterUpdateCounter = -1;
605          }          }
# Line 489  namespace LinuxSampler { namespace gig { Line 609  namespace LinuxSampler { namespace gig {
609          }          }
610      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
611    
         // ************************************************  
         // TODO: ARTICULATION DATA HANDLING IS MISSING HERE  
         // ************************************************  
   
612          return 0; // success          return 0; // success
613      }      }
614    
# Line 510  namespace LinuxSampler { namespace gig { Line 626  namespace LinuxSampler { namespace gig {
626      void Voice::Render(uint Samples) {      void Voice::Render(uint Samples) {
627    
628          // Reset the synthesis parameter matrix          // Reset the synthesis parameter matrix
629          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume);          pEngine->ResetSynthesisParameters(Event::destination_vca, this->Volume * this->CrossfadeVolume * pEngine->GlobalVolume);
630          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);          pEngine->ResetSynthesisParameters(Event::destination_vco, this->PitchBase);
631      #if ENABLE_FILTER      #if ENABLE_FILTER
632          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);          pEngine->ResetSynthesisParameters(Event::destination_vcfc, VCFCutoffCtrl.fvalue);
# Line 523  namespace LinuxSampler { namespace gig { Line 639  namespace LinuxSampler { namespace gig {
639    
640    
641          // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment          // Let all modulators write their parameter changes to the synthesis parameter matrix for the current audio fragment
642          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          pEG1->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend, itKillEvent);
643      #if ENABLE_FILTER      #if ENABLE_FILTER
644          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, pTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);          pEG2->Process(Samples, pEngine->pMIDIKeyInfo[MIDIKey].pEvents, itTriggerEvent, this->Pos, this->PitchBase * this->PitchBend);
645      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
646          pEG3->Process(Samples);          pEG3->Process(Samples);
647          pLFO1->Process(Samples);          pLFO1->Process(Samples);
# Line 535  namespace LinuxSampler { namespace gig { Line 651  namespace LinuxSampler { namespace gig {
651          pLFO3->Process(Samples);          pLFO3->Process(Samples);
652    
653    
654        #if ENABLE_FILTER
655            CalculateBiquadParameters(Samples); // calculate the final biquad filter parameters
656        #endif // ENABLE_FILTER
657    
658    
659          switch (this->PlaybackState) {          switch (this->PlaybackState) {
660    
661              case playback_state_ram: {              case playback_state_ram: {
662                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      if (RAMLoop) InterpolateAndLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
663                      else         Interpolate(Samples, (sample_t*) pSample->GetCache().pStart, Delay);                      else         InterpolateNoLoop(Samples, (sample_t*) pSample->GetCache().pStart, Delay);
664                      if (DiskVoice) {                      if (DiskVoice) {
665                          // check if we reached the allowed limit of the sample RAM cache                          // check if we reached the allowed limit of the sample RAM cache
666                          if (Pos > MaxRAMPos) {                          if (Pos > MaxRAMPos) {
# Line 559  namespace LinuxSampler { namespace gig { Line 680  namespace LinuxSampler { namespace gig {
680                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);                          DiskStreamRef.pStream = pDiskThread->AskForCreatedStream(DiskStreamRef.OrderID);
681                          if (!DiskStreamRef.pStream) {                          if (!DiskStreamRef.pStream) {
682                              std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;                              std::cout << stderr << "Disk stream not available in time!" << std::endl << std::flush;
683                              Kill();                              KillImmediately();
684                              return;                              return;
685                          }                          }
686                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));                          DiskStreamRef.pStream->IncrementReadPos(pSample->Channels * (RTMath::DoubleToInt(Pos) - MaxRAMPos));
# Line 567  namespace LinuxSampler { namespace gig { Line 688  namespace LinuxSampler { namespace gig {
688                      }                      }
689    
690                      // add silence sample at the end if we reached the end of the stream (for the interpolator)                      // add silence sample at the end if we reached the end of the stream (for the interpolator)
691                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {                      if (DiskStreamRef.State == Stream::state_end && DiskStreamRef.pStream->GetReadSpace() < (pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels) {
692                          DiskStreamRef.pStream->WriteSilence((MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);                          DiskStreamRef.pStream->WriteSilence((pEngine->MaxSamplesPerCycle << MAX_PITCH) / pSample->Channels);
693                          this->PlaybackState = playback_state_end;                          this->PlaybackState = playback_state_end;
694                      }                      }
695    
696                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from                      sample_t* ptr = DiskStreamRef.pStream->GetReadPtr(); // get the current read_ptr within the ringbuffer where we read the samples from
697                      Interpolate(Samples, ptr, Delay);                      InterpolateNoLoop(Samples, ptr, Delay);
698                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);                      DiskStreamRef.pStream->IncrementReadPos(RTMath::DoubleToInt(Pos) * pSample->Channels);
699                      Pos -= RTMath::DoubleToInt(Pos);                      Pos -= RTMath::DoubleToInt(Pos);
700                  }                  }
701                  break;                  break;
702    
703              case playback_state_end:              case playback_state_end:
704                  Kill(); // free voice                  KillImmediately(); // free voice
705                  break;                  break;
706          }          }
707    
708    
     #if ENABLE_FILTER  
709          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)          // Reset synthesis event lists (except VCO, as VCO events apply channel wide currently)
710            pEngine->pSynthesisEvents[Event::destination_vca]->clear();
711        #if ENABLE_FILTER
712          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfc]->clear();
713          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();          pEngine->pSynthesisEvents[Event::destination_vcfr]->clear();
714      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
# Line 594  namespace LinuxSampler { namespace gig { Line 716  namespace LinuxSampler { namespace gig {
716          // Reset delay          // Reset delay
717          Delay = 0;          Delay = 0;
718    
719          pTriggerEvent = NULL;          itTriggerEvent = Pool<Event>::Iterator();
720    
721          // If release stage finished, let the voice be killed          // If release stage finished, let the voice be killed
722          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;          if (pEG1->GetStage() == EGADSR::stage_end) this->PlaybackState = playback_state_end;
# Line 625  namespace LinuxSampler { namespace gig { Line 747  namespace LinuxSampler { namespace gig {
747      void Voice::ProcessEvents(uint Samples) {      void Voice::ProcessEvents(uint Samples) {
748    
749          // dispatch control change events          // dispatch control change events
750          Event* pCCEvent = pEngine->pCCEvents->first();          RTList<Event>::Iterator itCCEvent = pEngine->pCCEvents->first();
751          if (Delay) { // skip events that happened before this voice was triggered          if (Delay) { // skip events that happened before this voice was triggered
752              while (pCCEvent && pCCEvent->FragmentPos() <= Delay) pCCEvent = pEngine->pCCEvents->next();              while (itCCEvent && itCCEvent->FragmentPos() <= Delay) ++itCCEvent;
753          }          }
754          while (pCCEvent) {          while (itCCEvent) {
755              if (pCCEvent->Controller) { // if valid MIDI controller              if (itCCEvent->Param.CC.Controller) { // if valid MIDI controller
756                  #if ENABLE_FILTER                  #if ENABLE_FILTER
757                  if (pCCEvent->Controller == VCFCutoffCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFCutoffCtrl.controller) {
758                      pEngine->pSynthesisEvents[Event::destination_vcfc]->alloc_assign(*pCCEvent);                      *pEngine->pSynthesisEvents[Event::destination_vcfc]->allocAppend() = *itCCEvent;
759                  }                  }
760                  if (pCCEvent->Controller == VCFResonanceCtrl.controller) {                  if (itCCEvent->Param.CC.Controller == VCFResonanceCtrl.controller) {
761                      pEngine->pSynthesisEvents[Event::destination_vcfr]->alloc_assign(*pCCEvent);                      *pEngine->pSynthesisEvents[Event::destination_vcfr]->allocAppend() = *itCCEvent;
762                  }                  }
763                  #endif // ENABLE_FILTER                  #endif // ENABLE_FILTER
764                  if (pCCEvent->Controller == pLFO1->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO1->ExtController) {
765                      pLFO1->SendEvent(pCCEvent);                      pLFO1->SendEvent(itCCEvent);
766                  }                  }
767                  #if ENABLE_FILTER                  #if ENABLE_FILTER
768                  if (pCCEvent->Controller == pLFO2->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO2->ExtController) {
769                      pLFO2->SendEvent(pCCEvent);                      pLFO2->SendEvent(itCCEvent);
770                  }                  }
771                  #endif // ENABLE_FILTER                  #endif // ENABLE_FILTER
772                  if (pCCEvent->Controller == pLFO3->ExtController) {                  if (itCCEvent->Param.CC.Controller == pLFO3->ExtController) {
773                      pLFO3->SendEvent(pCCEvent);                      pLFO3->SendEvent(itCCEvent);
774                    }
775                    if (pDimRgn->AttenuationController.type == ::gig::attenuation_ctrl_t::type_controlchange &&
776                        itCCEvent->Param.CC.Controller == pDimRgn->AttenuationController.controller_number) { // if crossfade event
777                        *pEngine->pSynthesisEvents[Event::destination_vca]->allocAppend() = *itCCEvent;
778                  }                  }
779              }              }
780    
781              pCCEvent = pEngine->pCCEvents->next();              ++itCCEvent;
782          }          }
783    
784    
785          // process pitch events          // process pitch events
786          {          {
787              RTEList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];              RTList<Event>* pVCOEventList = pEngine->pSynthesisEvents[Event::destination_vco];
788              Event* pVCOEvent = pVCOEventList->first();              RTList<Event>::Iterator itVCOEvent = pVCOEventList->first();
789              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
790                  while (pVCOEvent && pVCOEvent->FragmentPos() <= Delay) pVCOEvent = pVCOEventList->next();                  while (itVCOEvent && itVCOEvent->FragmentPos() <= Delay) ++itVCOEvent;
791              }              }
792              // apply old pitchbend value until first pitch event occurs              // apply old pitchbend value until first pitch event occurs
793              if (this->PitchBend != 1.0) {              if (this->PitchBend != 1.0) {
794                  uint end = (pVCOEvent) ? pVCOEvent->FragmentPos() : Samples;                  uint end = (itVCOEvent) ? itVCOEvent->FragmentPos() : Samples;
795                  for (uint i = Delay; i < end; i++) {                  for (uint i = Delay; i < end; i++) {
796                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= this->PitchBend;
797                  }                  }
798              }              }
799              float pitch;              float pitch;
800              while (pVCOEvent) {              while (itVCOEvent) {
801                  Event* pNextVCOEvent = pVCOEventList->next();                  RTList<Event>::Iterator itNextVCOEvent = itVCOEvent;
802                    ++itNextVCOEvent;
803    
804                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
805                  uint end = (pNextVCOEvent) ? pNextVCOEvent->FragmentPos() : Samples;                  uint end = (itNextVCOEvent) ? itNextVCOEvent->FragmentPos() : Samples;
806    
807                  pitch = RTMath::CentsToFreqRatio(((double) pVCOEvent->Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents                  pitch = RTMath::CentsToFreqRatio(((double) itVCOEvent->Param.Pitch.Pitch / 8192.0) * 200.0); // +-two semitones = +-200 cents
808    
809                  // apply pitch value to the pitch parameter sequence                  // apply pitch value to the pitch parameter sequence
810                  for (uint i = pVCOEvent->FragmentPos(); i < end; i++) {                  for (uint i = itVCOEvent->FragmentPos(); i < end; i++) {
811                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;                      pEngine->pSynthesisParameters[Event::destination_vco][i] *= pitch;
812                  }                  }
813    
814                  pVCOEvent = pNextVCOEvent;                  itVCOEvent = itNextVCOEvent;
815              }              }
816              if (pVCOEventList->last()) this->PitchBend = pitch;              if (!pVCOEventList->isEmpty()) this->PitchBend = pitch;
817          }          }
818    
819            // process volume / attenuation events (TODO: we only handle and _expect_ crossfade events here ATM !)
820            {
821                RTList<Event>* pVCAEventList = pEngine->pSynthesisEvents[Event::destination_vca];
822                RTList<Event>::Iterator itVCAEvent = pVCAEventList->first();
823                if (Delay) { // skip events that happened before this voice was triggered
824                    while (itVCAEvent && itVCAEvent->FragmentPos() <= Delay) ++itVCAEvent;
825                }
826                float crossfadevolume;
827                while (itVCAEvent) {
828                    RTList<Event>::Iterator itNextVCAEvent = itVCAEvent;
829                    ++itNextVCAEvent;
830    
831                    // calculate the influence length of this event (in sample points)
832                    uint end = (itNextVCAEvent) ? itNextVCAEvent->FragmentPos() : Samples;
833    
834                    crossfadevolume = CrossfadeAttenuation(itVCAEvent->Param.CC.Value);
835    
836                    float effective_volume = crossfadevolume * this->Volume * pEngine->GlobalVolume;
837    
838                    // apply volume value to the volume parameter sequence
839                    for (uint i = itVCAEvent->FragmentPos(); i < end; i++) {
840                        pEngine->pSynthesisParameters[Event::destination_vca][i] = effective_volume;
841                    }
842    
843                    itVCAEvent = itNextVCAEvent;
844                }
845                if (!pVCAEventList->isEmpty()) this->CrossfadeVolume = crossfadevolume;
846            }
847    
848      #if ENABLE_FILTER      #if ENABLE_FILTER
849          // process filter cutoff events          // process filter cutoff events
850          {          {
851              RTEList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];              RTList<Event>* pCutoffEventList = pEngine->pSynthesisEvents[Event::destination_vcfc];
852              Event* pCutoffEvent = pCutoffEventList->first();              RTList<Event>::Iterator itCutoffEvent = pCutoffEventList->first();
853              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
854                  while (pCutoffEvent && pCutoffEvent->FragmentPos() <= Delay) pCutoffEvent = pCutoffEventList->next();                  while (itCutoffEvent && itCutoffEvent->FragmentPos() <= Delay) ++itCutoffEvent;
855              }              }
856              float cutoff;              float cutoff;
857              while (pCutoffEvent) {              while (itCutoffEvent) {
858                  Event* pNextCutoffEvent = pCutoffEventList->next();                  RTList<Event>::Iterator itNextCutoffEvent = itCutoffEvent;
859                    ++itNextCutoffEvent;
860    
861                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
862                  uint end = (pNextCutoffEvent) ? pNextCutoffEvent->FragmentPos() : Samples;                  uint end = (itNextCutoffEvent) ? itNextCutoffEvent->FragmentPos() : Samples;
863    
864                  cutoff = exp((float) pCutoffEvent->Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;                  cutoff = exp((float) itCutoffEvent->Param.CC.Value * 0.00787402f * FILTER_CUTOFF_COEFF) * FILTER_CUTOFF_MAX - FILTER_CUTOFF_MIN;
865    
866                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
867                  for (uint i = pCutoffEvent->FragmentPos(); i < end; i++) {                  for (uint i = itCutoffEvent->FragmentPos(); i < end; i++) {
868                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;                      pEngine->pSynthesisParameters[Event::destination_vcfc][i] = cutoff;
869                  }                  }
870    
871                  pCutoffEvent = pNextCutoffEvent;                  itCutoffEvent = itNextCutoffEvent;
872              }              }
873              if (pCutoffEventList->last()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time              if (!pCutoffEventList->isEmpty()) VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of parameter matrix next time
874          }          }
875    
876          // process filter resonance events          // process filter resonance events
877          {          {
878              RTEList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];              RTList<Event>* pResonanceEventList = pEngine->pSynthesisEvents[Event::destination_vcfr];
879              Event* pResonanceEvent = pResonanceEventList->first();              RTList<Event>::Iterator itResonanceEvent = pResonanceEventList->first();
880              if (Delay) { // skip events that happened before this voice was triggered              if (Delay) { // skip events that happened before this voice was triggered
881                  while (pResonanceEvent && pResonanceEvent->FragmentPos() <= Delay) pResonanceEvent = pResonanceEventList->next();                  while (itResonanceEvent && itResonanceEvent->FragmentPos() <= Delay) ++itResonanceEvent;
882              }              }
883              while (pResonanceEvent) {              while (itResonanceEvent) {
884                  Event* pNextResonanceEvent = pResonanceEventList->next();                  RTList<Event>::Iterator itNextResonanceEvent = itResonanceEvent;
885                    ++itNextResonanceEvent;
886    
887                  // calculate the influence length of this event (in sample points)                  // calculate the influence length of this event (in sample points)
888                  uint end = (pNextResonanceEvent) ? pNextResonanceEvent->FragmentPos() : Samples;                  uint end = (itNextResonanceEvent) ? itNextResonanceEvent->FragmentPos() : Samples;
889    
890                  // convert absolute controller value to differential                  // convert absolute controller value to differential
891                  int ctrldelta = pResonanceEvent->Value - VCFResonanceCtrl.value;                  int ctrldelta = itResonanceEvent->Param.CC.Value - VCFResonanceCtrl.value;
892                  VCFResonanceCtrl.value = pResonanceEvent->Value;                  VCFResonanceCtrl.value = itResonanceEvent->Param.CC.Value;
893    
894                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0                  float resonancedelta = (float) ctrldelta * 0.00787f; // 0.0..1.0
895    
896                  // apply cutoff frequency to the cutoff parameter sequence                  // apply cutoff frequency to the cutoff parameter sequence
897                  for (uint i = pResonanceEvent->FragmentPos(); i < end; i++) {                  for (uint i = itResonanceEvent->FragmentPos(); i < end; i++) {
898                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;                      pEngine->pSynthesisParameters[Event::destination_vcfr][i] += resonancedelta;
899                  }                  }
900    
901                  pResonanceEvent = pNextResonanceEvent;                  itResonanceEvent = itNextResonanceEvent;
902              }              }
903              if (pResonanceEventList->last()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Value * 0.00787f; // needed for initialization of parameter matrix next time              if (!pResonanceEventList->isEmpty()) VCFResonanceCtrl.fvalue = pResonanceEventList->last()->Param.CC.Value * 0.00787f; // needed for initialization of parameter matrix next time
904          }          }
905      #endif // ENABLE_FILTER      #endif // ENABLE_FILTER
906      }      }
907    
908        #if ENABLE_FILTER
909      /**      /**
910       *  Interpolates the input audio data (no loop).       * Calculate all necessary, final biquad filter parameters.
911         *
912         * @param Samples - number of samples to be rendered in this audio fragment cycle
913         */
914        void Voice::CalculateBiquadParameters(uint Samples) {
915            if (!FilterLeft.Enabled) return;
916    
917            biquad_param_t bqbase;
918            biquad_param_t bqmain;
919            float prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][0];
920            float prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][0];
921            FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
922            pEngine->pBasicFilterParameters[0] = bqbase;
923            pEngine->pMainFilterParameters[0]  = bqmain;
924    
925            float* bq;
926            for (int i = 1; i < Samples; i++) {
927                // recalculate biquad parameters if cutoff or resonance differ from previous sample point
928                if (!(i & FILTER_UPDATE_MASK)) if (pEngine->pSynthesisParameters[Event::destination_vcfr][i] != prev_res ||
929                                                   pEngine->pSynthesisParameters[Event::destination_vcfc][i] != prev_cutoff) {
930                    prev_cutoff = pEngine->pSynthesisParameters[Event::destination_vcfc][i];
931                    prev_res    = pEngine->pSynthesisParameters[Event::destination_vcfr][i];
932                    FilterLeft.SetParameters(&bqbase, &bqmain, prev_cutoff, prev_res, pEngine->SampleRate);
933                }
934    
935                //same as 'pEngine->pBasicFilterParameters[i] = bqbase;'
936                bq    = (float*) &pEngine->pBasicFilterParameters[i];
937                bq[0] = bqbase.a1;
938                bq[1] = bqbase.a2;
939                bq[2] = bqbase.b0;
940                bq[3] = bqbase.b1;
941                bq[4] = bqbase.b2;
942    
943                // same as 'pEngine->pMainFilterParameters[i] = bqmain;'
944                bq    = (float*) &pEngine->pMainFilterParameters[i];
945                bq[0] = bqmain.a1;
946                bq[1] = bqmain.a2;
947                bq[2] = bqmain.b0;
948                bq[3] = bqmain.b1;
949                bq[4] = bqmain.b2;
950            }
951        }
952        #endif // ENABLE_FILTER
953    
954        /**
955         *  Interpolates the input audio data (without looping).
956       *       *
957       *  @param Samples - number of sample points to be rendered in this audio       *  @param Samples - number of sample points to be rendered in this audio
958       *                   fragment cycle       *                   fragment cycle
959       *  @param pSrc    - pointer to input sample data       *  @param pSrc    - pointer to input sample data
960       *  @param Skip    - number of sample points to skip in output buffer       *  @param Skip    - number of sample points to skip in output buffer
961       */       */
962      void Voice::Interpolate(uint Samples, sample_t* pSrc, uint Skip) {      void Voice::InterpolateNoLoop(uint Samples, sample_t* pSrc, uint Skip) {
963          int i = Skip;          int i = Skip;
964    
965          // FIXME: assuming either mono or stereo          // FIXME: assuming either mono or stereo
966          if (this->pSample->Channels == 2) { // Stereo Sample          if (this->pSample->Channels == 2) { // Stereo Sample
967              while (i < Samples) {              while (i < Samples) InterpolateStereo(pSrc, i);
                 InterpolateOneStep_Stereo(pSrc, i,  
                                           pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                           pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                           pEngine->pSynthesisParameters[Event::destination_vcfc][i],  
                                           pEngine->pSynthesisParameters[Event::destination_vcfr][i]);  
             }  
968          }          }
969          else { // Mono Sample          else { // Mono Sample
970              while (i < Samples) {              while (i < Samples) InterpolateMono(pSrc, i);
                 InterpolateOneStep_Mono(pSrc, i,  
                                         pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                         pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                         pEngine->pSynthesisParameters[Event::destination_vcfc][i],  
                                         pEngine->pSynthesisParameters[Event::destination_vcfr][i]);  
             }  
971          }          }
972      }      }
973    
# Line 796  namespace LinuxSampler { namespace gig { Line 987  namespace LinuxSampler { namespace gig {
987              if (pSample->LoopPlayCount) {              if (pSample->LoopPlayCount) {
988                  // render loop (loop count limited)                  // render loop (loop count limited)
989                  while (i < Samples && LoopCyclesLeft) {                  while (i < Samples && LoopCyclesLeft) {
990                      InterpolateOneStep_Stereo(pSrc, i,                      InterpolateStereo(pSrc, i);
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vcfc][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vcfr][i]);  
991                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
992                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
993                          LoopCyclesLeft--;                          LoopCyclesLeft--;
994                      }                      }
995                  }                  }
996                  // render on without loop                  // render on without loop
997                  while (i < Samples) {                  while (i < Samples) InterpolateStereo(pSrc, i);
                     InterpolateOneStep_Stereo(pSrc, i,  
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vcfc][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vcfr][i]);  
                 }  
998              }              }
999              else { // render loop (endless loop)              else { // render loop (endless loop)
1000                  while (i < Samples) {                  while (i < Samples) {
1001                      InterpolateOneStep_Stereo(pSrc, i,                      InterpolateStereo(pSrc, i);
                                               pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vcfc][i],  
                                               pEngine->pSynthesisParameters[Event::destination_vcfr][i]);  
1002                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1003                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);
1004                      }                      }
# Line 832  namespace LinuxSampler { namespace gig { Line 1009  namespace LinuxSampler { namespace gig {
1009              if (pSample->LoopPlayCount) {              if (pSample->LoopPlayCount) {
1010                  // render loop (loop count limited)                  // render loop (loop count limited)
1011                  while (i < Samples && LoopCyclesLeft) {                  while (i < Samples && LoopCyclesLeft) {
1012                      InterpolateOneStep_Mono(pSrc, i,                      InterpolateMono(pSrc, i);
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vcfc][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vcfr][i]);  
1013                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1014                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1015                          LoopCyclesLeft--;                          LoopCyclesLeft--;
1016                      }                      }
1017                  }                  }
1018                  // render on without loop                  // render on without loop
1019                  while (i < Samples) {                  while (i < Samples) InterpolateMono(pSrc, i);
                     InterpolateOneStep_Mono(pSrc, i,  
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vcfc][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vcfr][i]);  
                 }  
1020              }              }
1021              else { // render loop (endless loop)              else { // render loop (endless loop)
1022                  while (i < Samples) {                  while (i < Samples) {
1023                      InterpolateOneStep_Mono(pSrc, i,                      InterpolateMono(pSrc, i);
                                             pEngine->pSynthesisParameters[Event::destination_vca][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vco][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vcfc][i],  
                                             pEngine->pSynthesisParameters[Event::destination_vcfr][i]);  
1024                      if (Pos > pSample->LoopEnd) {                      if (Pos > pSample->LoopEnd) {
1025                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;                          Pos = pSample->LoopStart + fmod(Pos - pSample->LoopEnd, pSample->LoopSize);;
1026                      }                      }
# Line 867  namespace LinuxSampler { namespace gig { Line 1030  namespace LinuxSampler { namespace gig {
1030      }      }
1031    
1032      /**      /**
1033       *  Immediately kill the voice.       *  Immediately kill the voice. This method should not be used to kill
1034         *  a normal, active voice, because it doesn't take care of things like
1035         *  fading down the volume level to avoid clicks and regular processing
1036         *  until the kill event actually occured!
1037         *
1038         *  @see Kill()
1039       */       */
1040      void Voice::Kill() {      void Voice::KillImmediately() {
1041          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {          if (DiskVoice && DiskStreamRef.State != Stream::state_unused) {
1042              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);              pDiskThread->OrderDeletionOfStream(&DiskStreamRef);
1043          }          }
1044          Reset();          Reset();
1045      }      }
1046    
1047        /**
1048         *  Kill the voice in regular sense. Let the voice render audio until
1049         *  the kill event actually occured and then fade down the volume level
1050         *  very quickly and let the voice die finally. Unlike a normal release
1051         *  of a voice, a kill process cannot be cancalled and is therefore
1052         *  usually used for voice stealing and key group conflicts.
1053         *
1054         *  @param itKillEvent - event which caused the voice to be killed
1055         */
1056        void Voice::Kill(Pool<Event>::Iterator& itKillEvent) {
1057            if (itTriggerEvent && itKillEvent->FragmentPos() <= itTriggerEvent->FragmentPos()) return;
1058            this->itKillEvent = itKillEvent;
1059        }
1060    
1061  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.56  
changed lines
  Added in v.271

  ViewVC Help
Powered by ViewVC