/[svn]/linuxsampler/trunk/src/engines/common/LFOTriangleDiHarmonic.h
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/common/LFOTriangleDiHarmonic.h

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

revision 717 by schoenebeck, Sun Jul 24 10:26:17 2005 UTC revision 2227 by iliev, Wed Aug 3 17:11:40 2011 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   Copyright (C) 2005 Christian Schoenebeck                              *   *   Copyright (C) 2005, 2008 Christian Schoenebeck                        *
4   *                                                                         *   *                                                                         *
5   *   This library is free software; you can redistribute it and/or modify  *   *   This library is free software; you can redistribute it and/or modify  *
6   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 24  Line 24 
24  #include "LFOBase.h"  #include "LFOBase.h"
25    
26  // amplitue of 2nd harmonic (to approximate the triangular wave)  // amplitue of 2nd harmonic (to approximate the triangular wave)
27  // TODO: this was just a quick head calculation, needs to be recalculated exactly (DFT)  #define AMP2    -0.11425509f
 #define AMP2    0.1f  
28    
29  namespace LinuxSampler {  namespace LinuxSampler {
30    
# Line 58  namespace LinuxSampler { Line 57  namespace LinuxSampler {
57                  real2 -= c2 * imag2;                  real2 -= c2 * imag2;
58                  imag2 += c2 * real2;                  imag2 += c2 * real2;
59                  if (RANGE == range_unsigned)                  if (RANGE == range_unsigned)
60                      return (real1 + real2 * AMP2) * normalizer + normalizer;                      return (real1 + real2 * AMP2) * normalizer + offset;
61                  else /* signed range */                  else /* signed range */
62                      return (real1 + real2 * AMP2) * normalizer;                      return (real1 + real2 * AMP2) * normalizer;
63              }              }
# Line 69  namespace LinuxSampler { Line 68  namespace LinuxSampler {
68               * @param ExtControlValue - new external controller value               * @param ExtControlValue - new external controller value
69               */               */
70              inline void update(const uint16_t& ExtControlValue) {              inline void update(const uint16_t& ExtControlValue) {
71                  const float max = InternalDepth + ExtControlValue * ExtControlDepthCoeff;                  const float max = this->InternalDepth + ExtControlValue * this->ExtControlDepthCoeff;
72                  if (RANGE == range_unsigned)                  if (RANGE == range_unsigned) {
73                        const float harmonicCompensation = 1.0f + fabsf(AMP2); // to compensate the compensation ;) (see trigger())
74                      normalizer = max * 0.5f;                      normalizer = max * 0.5f;
75                  else /* signed range */                      offset     = normalizer * harmonicCompensation;
76                    } else { // signed range
77                      normalizer = max;                      normalizer = max;
78                    }
79              }              }
80    
81              /**              /**
# Line 85  namespace LinuxSampler { Line 87  namespace LinuxSampler {
87               * @param ExtControlDepth - defines how strong the external MIDI               * @param ExtControlDepth - defines how strong the external MIDI
88               *                          controller has influence on the               *                          controller has influence on the
89               *                          oscillator amplitude               *                          oscillator amplitude
90               * @param FlipPhase       - inverts the oscillator wave               * @param FlipPhase       - inverts the oscillator wave against
91                 *                          a horizontal axis
92               * @param SampleRate      - current sample rate of the engines               * @param SampleRate      - current sample rate of the engines
93               *                          audio output signal               *                          audio output signal
94               */               */
95              void trigger(float Frequency, start_level_t StartLevel, uint16_t InternalDepth, uint16_t ExtControlDepth, bool FlipPhase, unsigned int SampleRate) {              void trigger(float Frequency, start_level_t StartLevel, uint16_t InternalDepth, uint16_t ExtControlDepth, bool FlipPhase, unsigned int SampleRate) {
96                  this->InternalDepth        = (InternalDepth / 1200.0f) * Max;                  const float harmonicCompensation = 1.0f + fabsf(AMP2); // to compensate the 2nd harmonic's amplitude overhead
97                  this->ExtControlDepthCoeff = (((float) ExtControlDepth / 1200.0f) / 127.0f) * Max;                  this->InternalDepth        = (InternalDepth / 1200.0f) * this->Max / harmonicCompensation;
98                    this->ExtControlDepthCoeff = (((float) ExtControlDepth / 1200.0f) / 127.0f) * this->Max / harmonicCompensation;
99    
100                  c1 = 2.0f * M_PI * Frequency / (float) SampleRate;                  c1 = 2.0f * M_PI * Frequency / (float) SampleRate;
101                  c2 = 2.0f * M_PI * Frequency / (float) SampleRate * 3.0f;                  c2 = 2.0f * M_PI * Frequency / (float) SampleRate * 3.0f;
102    
103                  float phi; // phase displacement                  double phi; // phase displacement
104                  switch (StartLevel) {                  switch (StartLevel) {
                     case start_level_max:  
                         phi = 0.0f; // 0°  
                         break;  
105                      case start_level_mid:                      case start_level_mid:
106                          phi = (FlipPhase) ? 3.0f * M_PI : M_PI; // 270° or 90°                          //FIXME: direct jumping to 90° and 270° doesn't work out due to numeric accuracy problems (causes wave deformation)
107                            //phi = (FlipPhase) ? 0.5 * M_PI : 1.5 * M_PI; // 90° or 270°
108                            //break;
109                        case start_level_max:
110                            phi = (FlipPhase) ? M_PI : 0.0; // 180° or 0°
111                          break;                          break;
112                      case start_level_min:                      case start_level_min:
113                          phi = 2.0f * M_PI; // 180°                          phi = (FlipPhase) ? 0.0 : M_PI; // 0° or 180°
114                          break;                          break;
115                  }                  }
116                  real1 = real2 = cos(phi);                  real1 = real2 = cos(phi);
117                  imag1 = imag2 = sin(phi);                  imag1 = imag2 = sin(phi);
118              }              }
119                
120                /**
121                 * Should be invoked after the LFO is triggered with StartLevel
122                 * start_level_min.
123                 * @param phase From 0 to 360 degrees.
124                 */
125                void setPhase(float phase) {
126                    if (phase < 0) phase = 0;
127                    if (phase > 360) phase = 360;
128                    phase /= 360.0f;
129                    
130                    // FIXME: too heavy?
131                    float steps = 1.0f / (c1 / (2.0f * M_PI)); // number of steps for one cycle
132                    steps *= phase + 0.25f;
133                    for (int i = 0; i < steps; i++) render();
134                }
135                
136                void setFrequency(float Frequency, unsigned int SampleRate) {
137                    c1 = 2.0f * M_PI * Frequency / (float) SampleRate;
138                    c2 = 2.0f * M_PI * Frequency / (float) SampleRate * 3.0f;
139                }
140    
141          private:          private:
142              float c1;              float c1;
# Line 120  namespace LinuxSampler { Line 146  namespace LinuxSampler {
146              float real2;              float real2;
147              float imag2;              float imag2;
148              float normalizer;              float normalizer;
149                float offset;
150      };      };
151    
152  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.717  
changed lines
  Added in v.2227

  ViewVC Help
Powered by ViewVC