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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2227 - (hide annotations) (download) (as text)
Wed Aug 3 17:11:40 2011 UTC (12 years, 8 months ago) by iliev
File MIME type: text/x-c++hdr
File size: 7071 byte(s)
* sfz engine: implemented opcodes fillfo_freqccN,
  pitchlfo_freqccN, amplfo_freqccN, lfoN_freq_onccX

1 schoenebeck 717 /***************************************************************************
2     * *
3 schoenebeck 1681 * Copyright (C) 2005, 2008 Christian Schoenebeck *
4 schoenebeck 717 * *
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 schoenebeck 1681 #define AMP2 -0.11425509f
28 schoenebeck 717
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 schoenebeck 721 return (real1 + real2 * AMP2) * normalizer + offset;
61 schoenebeck 717 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 senkov 719 const float max = this->InternalDepth + ExtControlValue * this->ExtControlDepthCoeff;
72 schoenebeck 721 if (RANGE == range_unsigned) {
73 schoenebeck 1681 const float harmonicCompensation = 1.0f + fabsf(AMP2); // to compensate the compensation ;) (see trigger())
74 schoenebeck 717 normalizer = max * 0.5f;
75 schoenebeck 721 offset = normalizer * harmonicCompensation;
76     } else { // signed range
77 schoenebeck 717 normalizer = max;
78 schoenebeck 721 }
79 schoenebeck 717 }
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 schoenebeck 721 * @param FlipPhase - inverts the oscillator wave against
91     * a horizontal axis
92 schoenebeck 717 * @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 schoenebeck 1681 const float harmonicCompensation = 1.0f + fabsf(AMP2); // to compensate the 2nd harmonic's amplitude overhead
97     this->InternalDepth = (InternalDepth / 1200.0f) * this->Max / harmonicCompensation;
98 schoenebeck 721 this->ExtControlDepthCoeff = (((float) ExtControlDepth / 1200.0f) / 127.0f) * this->Max / harmonicCompensation;
99 schoenebeck 717
100     c1 = 2.0f * M_PI * Frequency / (float) SampleRate;
101     c2 = 2.0f * M_PI * Frequency / (float) SampleRate * 3.0f;
102    
103 schoenebeck 721 double phi; // phase displacement
104 schoenebeck 717 switch (StartLevel) {
105 schoenebeck 721 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 schoenebeck 717 case start_level_max:
110 schoenebeck 721 phi = (FlipPhase) ? M_PI : 0.0; // 180� or 0�
111 schoenebeck 717 break;
112     case start_level_min:
113 schoenebeck 721 phi = (FlipPhase) ? 0.0 : M_PI; // 0� or 180�
114 schoenebeck 717 break;
115     }
116     real1 = real2 = cos(phi);
117     imag1 = imag2 = sin(phi);
118     }
119 iliev 2225
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 iliev 2227
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 schoenebeck 717
141     private:
142     float c1;
143     float c2;
144     float real1;
145     float imag1;
146     float real2;
147     float imag2;
148     float normalizer;
149 schoenebeck 721 float offset;
150 schoenebeck 717 };
151    
152     } // namespace LinuxSampler
153    
154     #endif // __LS_LFOTRIANGLEDIHARMONIC_H__

  ViewVC Help
Powered by ViewVC