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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 721 - (show annotations) (download) (as text)
Sun Jul 24 19:44:44 2005 UTC (18 years, 8 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 6191 byte(s)
- fixed di-harmonic triangle LFO implementation
- calculated exact amplitude coefficient of 2nd harmonic

1 /***************************************************************************
2 * *
3 * Copyright (C) 2005 Christian Schoenebeck *
4 * *
5 * 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 *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This library is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this library; if not, write to the Free Software *
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
18 * MA 02111-1307 USA *
19 ***************************************************************************/
20
21 #ifndef __LS_LFOTRIANGLEDIHARMONIC_H__
22 #define __LS_LFOTRIANGLEDIHARMONIC_H__
23
24 #include "LFOBase.h"
25
26 // amplitue of 2nd harmonic (to approximate the triangular wave)
27 #define AMP2 0.11425509f
28
29 namespace LinuxSampler {
30
31 /** @brief Triangle LFO (di-harmonic implementation)
32 *
33 * This is a triangle Low Frequency Oscillator implementation which uses
34 * a di-harmonic solution. This means it sums up two harmonics
35 * (sinusoids) to approximate a triangular wave.
36 */
37 template<range_type_t RANGE>
38 class LFOTriangleDiHarmonic : public LFOBase<RANGE> {
39 public:
40
41 /**
42 * Constructor
43 *
44 * @param Max - maximum value of the output levels
45 */
46 LFOTriangleDiHarmonic(float Max) : LFOBase<RANGE>::LFOBase(Max) {
47 }
48
49 /**
50 * Calculates exactly one sample point of the LFO wave.
51 *
52 * @returns next LFO level
53 */
54 inline float render() {
55 real1 -= c1 * imag1;
56 imag1 += c1 * real1;
57 real2 -= c2 * imag2;
58 imag2 += c2 * real2;
59 if (RANGE == range_unsigned)
60 return (real1 + real2 * AMP2) * normalizer + offset;
61 else /* signed range */
62 return (real1 + real2 * AMP2) * normalizer;
63 }
64
65 /**
66 * Update LFO depth with a new external controller value.
67 *
68 * @param ExtControlValue - new external controller value
69 */
70 inline void update(const uint16_t& ExtControlValue) {
71 const float max = this->InternalDepth + ExtControlValue * this->ExtControlDepthCoeff;
72 if (RANGE == range_unsigned) {
73 const float harmonicCompensation = 1.0f + AMP2; // to compensate the compensation ;) (see trigger())
74 normalizer = max * 0.5f;
75 offset = normalizer * harmonicCompensation;
76 } else { // signed range
77 normalizer = max;
78 }
79 }
80
81 /**
82 * Will be called by the voice when the key / voice was triggered.
83 *
84 * @param Frequency - frequency of the oscillator in Hz
85 * @param StartLevel - on which level the wave should start
86 * @param InternalDepth - firm, internal oscillator amplitude
87 * @param ExtControlDepth - defines how strong the external MIDI
88 * controller has influence on the
89 * oscillator amplitude
90 * @param FlipPhase - inverts the oscillator wave against
91 * a horizontal axis
92 * @param SampleRate - current sample rate of the engines
93 * audio output signal
94 */
95 void trigger(float Frequency, start_level_t StartLevel, uint16_t InternalDepth, uint16_t ExtControlDepth, bool FlipPhase, unsigned int SampleRate) {
96 const float harmonicCompensation = 1.0f + AMP2; // to compensate the 2nd harmonic's amplitude overhead
97 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;
101 c2 = 2.0f * M_PI * Frequency / (float) SampleRate * 3.0f;
102
103 double phi; // phase displacement
104 switch (StartLevel) {
105 case start_level_mid:
106 //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;
112 case start_level_min:
113 phi = (FlipPhase) ? 0.0 : M_PI; // 0� or 180�
114 break;
115 }
116 real1 = real2 = cos(phi);
117 imag1 = imag2 = sin(phi);
118 }
119
120 private:
121 float c1;
122 float c2;
123 float real1;
124 float imag1;
125 float real2;
126 float imag2;
127 float normalizer;
128 float offset;
129 };
130
131 } // namespace LinuxSampler
132
133 #endif // __LS_LFOTRIANGLEDIHARMONIC_H__

  ViewVC Help
Powered by ViewVC