/[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 3654 by schoenebeck, Wed Dec 11 11:10:24 2019 UTC revision 3655 by schoenebeck, Fri Dec 13 17:14:48 2019 UTC
# Line 49  namespace LinuxSampler { namespace gig { Line 49  namespace LinuxSampler { namespace gig {
49          return static_cast<LFO::wave_t>(wave);          return static_cast<LFO::wave_t>(wave);
50      }      }
51    
52        // Returns true for GigaStudio's original filter types (which are resembled
53        // by LS very accurately with same frequency response and patch settings
54        // behaviour), false for our own LS specific filter implementation types.
55        constexpr bool isGStFilterType(::gig::vcf_type_t type) {
56            return type == ::gig::vcf_type_lowpass ||
57                   type == ::gig::vcf_type_lowpassturbo ||
58                   type == ::gig::vcf_type_bandpass ||
59                   type == ::gig::vcf_type_highpass ||
60                   type == ::gig::vcf_type_bandreject;
61        }
62    
63      Voice::Voice() {      Voice::Voice() {
64          pEngine = NULL;          pEngine = NULL;
65          pEG1 = &EG1;          pEG1 = &EG1;
# Line 153  namespace LinuxSampler { namespace gig { Line 164  namespace LinuxSampler { namespace gig {
164          // Not used so far          // Not used so far
165      }      }
166    
167        uint8_t Voice::MinCutoff() const {
168            // If there's a cutoff controller defined then VCFVelocityScale means
169            // "minimum cutoff". If there is no MIDI controller defined for cutoff
170            // then VCFVelocityScale is already taken into account on libgig side
171            // instead by call to pRegion->GetVelocityCutoff(MIDIKeyVelocity).
172            return pRegion->VCFVelocityScale;
173        }
174    
175        // This is called on any cutoff controller changes, however not when the
176        // voice is triggered. So the initial cutoff value is retrieved by a call
177        // to CalculateFinalCutoff() instead.
178      void Voice::ProcessCutoffEvent(RTList<Event>::Iterator& itEvent) {      void Voice::ProcessCutoffEvent(RTList<Event>::Iterator& itEvent) {
179          int ccvalue = itEvent->Param.CC.Value;          if (VCFCutoffCtrl.value == itEvent->Param.CC.Value) return;
180          if (VCFCutoffCtrl.value == ccvalue) return;          float ccvalue = VCFCutoffCtrl.value = itEvent->Param.CC.Value;
181          VCFCutoffCtrl.value = ccvalue;  
182          if (pRegion->VCFCutoffControllerInvert)  ccvalue = 127 - ccvalue;          // if the selected filter type is an official GigaStudio filter type
183          if (ccvalue < pRegion->VCFVelocityScale) ccvalue = pRegion->VCFVelocityScale;          // then we preserve the original (no matter how odd) historical GSt
184          float cutoff = CutoffBase * float(ccvalue);          // behaviour identically; for our own filter types though we deviate to
185            // more meaningful behaviours where appropriate
186            const bool isGStFilter = isGStFilterType(pRegion->VCFType);
187    
188            if (pRegion->VCFCutoffControllerInvert) ccvalue = 127 - ccvalue;
189            if (isGStFilter) {
190                // VCFVelocityScale in this case means "minimum cutoff" for GSt
191                if (ccvalue < MinCutoff()) ccvalue = MinCutoff();
192            } else {
193                // for our own filter types we interpret "minimum cutoff"
194                // differently: GSt handles this as a simple hard limit with the
195                // consequence that a certain range of the controller is simply
196                // dead; so for our filter types we rather remap that to
197                // restrain within the min_cutoff..127 range as well, but
198                // effectively spanned over the entire controller range (0..127)
199                // to avoid such a "dead" lower controller zone
200                ccvalue = MinCutoff() + (ccvalue / 127.f) * float(127 - MinCutoff());
201            }
202    
203            float cutoff = CutoffBase * ccvalue;
204          if (cutoff > 127.0f) cutoff = 127.0f;          if (cutoff > 127.0f) cutoff = 127.0f;
205    
206          VCFCutoffCtrl.fvalue = cutoff; // needed for initialization of fFinalCutoff next time          // the filter implementations of the original GSt filter types take an
207          fFinalCutoff = cutoff;          // abstract cutoff parameter range of 0..127, whereas our own filter
208            // types take a cutoff parameter in Hz, so remap here:
209            // 0 .. 127 [lin] -> 21 Hz .. 18 kHz [x^4] (center @2.2 kHz)
210            if (!isGStFilter) {
211                cutoff = (cutoff + 29.f) / (127.f + 29.f);
212                cutoff = cutoff * cutoff * cutoff * cutoff * 18000.f;
213                if (cutoff > 0.49f * pEngine->SampleRate)
214                    cutoff = 0.49f * pEngine->SampleRate;
215            }
216    
217            fFinalCutoff = VCFCutoffCtrl.fvalue = cutoff;
218      }      }
219    
220      double Voice::CalculateCrossfadeVolume(uint8_t MIDIKeyVelocity) {      double Voice::CalculateCrossfadeVolume(uint8_t MIDIKeyVelocity) {
# Line 429  namespace LinuxSampler { namespace gig { Line 480  namespace LinuxSampler { namespace gig {
480          return cutoff;          return cutoff;
481      }      }
482    
483      /// Returns true for GigaStudio's original filter types.      // This is just called when the voice is triggered. On any subsequent cutoff
484      constexpr bool isGStFilterType(::gig::vcf_type_t type) {      // controller changes ProcessCutoffEvent() is called instead.
         return type == ::gig::vcf_type_lowpass ||  
                type == ::gig::vcf_type_lowpassturbo ||  
                type == ::gig::vcf_type_bandpass ||  
                type == ::gig::vcf_type_highpass ||  
                type == ::gig::vcf_type_bandreject;  
     }  
   
485      float Voice::CalculateFinalCutoff(float cutoffBase) {      float Voice::CalculateFinalCutoff(float cutoffBase) {
486          int cvalue;          // if the selected filter type is an official GigaStudio filter type
487            // then we preserve the original (no matter how odd) historical GSt
488            // behaviour identically; for our own filter types though we deviate to
489            // more meaningful behaviours where appropriate
490            const bool isGStFilter = isGStFilterType(pRegion->VCFType);
491    
492            // get current cutoff CC or velocity value (always 0..127)
493            float cvalue;
494          if (VCFCutoffCtrl.controller) {          if (VCFCutoffCtrl.controller) {
495              cvalue = GetGigEngineChannel()->ControllerTable[VCFCutoffCtrl.controller];              cvalue = GetGigEngineChannel()->ControllerTable[VCFCutoffCtrl.controller];
496              if (pRegion->VCFCutoffControllerInvert) cvalue = 127 - cvalue;              if (pRegion->VCFCutoffControllerInvert) cvalue = 127 - cvalue;
497              // VCFVelocityScale in this case means Minimum cutoff              if (isGStFilter) {
498              if (cvalue < pRegion->VCFVelocityScale) cvalue = pRegion->VCFVelocityScale;                  // VCFVelocityScale in this case means "minimum cutoff" for GSt
499          }                  if (cvalue < MinCutoff()) cvalue = MinCutoff();
500          else {              } else {
501                    // for our own filter types we interpret "minimum cutoff"
502                    // differently: GSt handles this as a simple hard limit with the
503                    // consequence that a certain range of the controller is simply
504                    // dead; so for our filter types we rather remap that to
505                    // restrain within the min_cutoff..127 range as well, but
506                    // effectively spanned over the entire controller range (0..127)
507                    // to avoid such a "dead" lower controller zone
508                    cvalue = MinCutoff() + (cvalue / 127.f) * float(127 - MinCutoff());
509                }
510            } else {
511                // in case of velocity, VCFVelocityScale parameter is already
512                // handled on libgig side (so by calling
513                // pRegion->GetVelocityCutoff(velo) in CalculateCutoffBase() above)
514              cvalue = pRegion->VCFCutoff;              cvalue = pRegion->VCFCutoff;
515          }          }
516          float fco = cutoffBase * float(cvalue);  
517            float fco = cutoffBase * cvalue;
518          if (fco > 127.0f) fco = 127.0f;          if (fco > 127.0f) fco = 127.0f;
519    
520          // the filter implementations of the original GSt filter types take an          // the filter implementations of the original GSt filter types take an
521          // abstract cutoff parameter range of 0..127, ...          // abstract cutoff parameter range of 0..127, ...
522          if (isGStFilterType(pRegion->VCFType))          if (isGStFilter)
523              return fco;              return fco;
524    
525          // ... whereas our own filter types take a cutoff parameter in Hz, so          // ... whereas our own filter types take a cutoff parameter in Hz, so

Legend:
Removed from v.3654  
changed lines
  Added in v.3655

  ViewVC Help
Powered by ViewVC