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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3612 - (show annotations) (download) (as text)
Mon Sep 30 18:03:43 2019 UTC (4 years, 6 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 8880 byte(s)
Added new LFO implementations:

* Added int math square LFO implementation.

* Added int math saw LFO implementation.

* Added numeric complex nr sine LFO implementation.

* Added public API C++ class "LFO", which is a cluster class
  encapsulating all the sampler's LFO implementations to be used by
  3rd party applications (e.g. by Gigedit).

* Marked class LFOTriangleDiHarmonic as deprecated
  (will be removed in future).

* Added LFOAll.h which includes all LFO implementation's header files.

* Fixed benchmarks/triang.cpp falsely having favoured "int math abs"
  algorithm (since result of 2nd run was not accumulated).

* Added benchmark for saw wave (benchmarks/saw.cpp).

* Added benchmark for sine wave (benchmarks/sine.cpp).

* Added benchmark for square wave (benchmarks/square.cpp).

* Increased amount of benchmarks runs by factor 6 to achieve benchmark
  times which are large enough on modern systems.

* Cleanup of LFO APIs.

* Bumped version (2.1.1.svn18).

1 /***************************************************************************
2 * *
3 * Copyright (C) 2005 - 2019 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_LFOTRIANGLEINTMATH_H__
22 #define __LS_LFOTRIANGLEINTMATH_H__
23
24 #include "LFOBase.h"
25
26 namespace LinuxSampler {
27
28 /** @brief Triangle LFO (int math implementation)
29 *
30 * This is a triangle Low Frequency Oscillator which uses pure integer
31 * math (without branches) to synthesize the triangular wave.
32 */
33 template<LFO::range_type_t RANGE>
34 class LFOTriangleIntMath : public LFOBase<RANGE> {
35 public:
36
37 /**
38 * Constructor
39 *
40 * @param Max - maximum value of the output levels
41 */
42 LFOTriangleIntMath(float Max) : LFOBase<RANGE>::LFOBase(Max) {
43 }
44
45 /**
46 * Calculates exactly one sample point of the LFO wave.
47 *
48 * @returns next LFO level
49 */
50 inline float render() {
51 const int signshifts = (sizeof(int) * 8) - 1;
52 iLevel += c;
53 const int iSign = (iLevel >> signshifts) | 1;
54 if (RANGE == LFO::range_unsigned)
55 return normalizer * (float) (iSign * iLevel);
56 else /* signed range */
57 return normalizer * (float) (iSign * iLevel) + offset;
58 }
59
60 /**
61 * Update LFO depth with a new external controller value.
62 *
63 * @param ExtControlValue - new external controller value
64 */
65 inline void updateByMIDICtrlValue(const uint16_t& ExtControlValue) {
66 this->ExtControlValue = ExtControlValue;
67
68 const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
69 const float max = (this->InternalDepth + ExtControlValue * this->ExtControlDepthCoeff) * this->ScriptDepthFactor;
70 if (RANGE == LFO::range_unsigned) {
71 normalizer = max / (float) intLimit;
72 } else { // signed range
73 normalizer = max / (float) intLimit * 4.0f;
74 offset = -max;
75 }
76 }
77
78 /**
79 * Will be called by the voice when the key / voice was triggered.
80 *
81 * @param Frequency - frequency of the oscillator in Hz
82 * @param StartLevel - on which level the wave should start
83 * @param InternalDepth - firm, internal oscillator amplitude
84 * @param ExtControlDepth - defines how strong the external MIDI
85 * controller has influence on the
86 * oscillator amplitude
87 * @param FlipPhase - inverts the oscillator wave against
88 * a horizontal axis
89 * @param SampleRate - current sample rate of the engines
90 * audio output signal
91 */
92 void trigger(float Frequency, LFO::start_level_t StartLevel, uint16_t InternalDepth, uint16_t ExtControlDepth, bool FlipPhase, unsigned int SampleRate) {
93 this->Frequency = Frequency;
94 this->InternalDepth = (InternalDepth / 1200.0f) * this->Max;
95 this->ExtControlDepthCoeff = (((float) ExtControlDepth / 1200.0f) / 127.0f) * this->Max;
96 this->ScriptFrequencyFactor = this->ScriptDepthFactor = 1.f; // reset for new voice
97 if (RANGE == LFO::range_unsigned) {
98 this->InternalDepth *= 2.0f;
99 this->ExtControlDepthCoeff *= 2.0f;
100 }
101 this->pFinalDepth = NULL;
102 this->pFinalFrequency = NULL;
103
104 const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
105 const float freq = Frequency * this->ScriptFrequencyFactor;
106 const float r = freq / (float) SampleRate; // frequency alteration quotient
107 c = (int) (intLimit * r);
108
109 switch (StartLevel) {
110 case LFO::start_level_max:
111 iLevel = (FlipPhase) ? 0 : intLimit >> 1;
112 break;
113 case LFO::start_level_mid:
114 iLevel = (FlipPhase) ? intLimit / 4 * 3 : intLimit >> 2;
115 break;
116 case LFO::start_level_min:
117 iLevel = (FlipPhase) ? intLimit >> 1 : 0;
118 break;
119 }
120 }
121
122 /**
123 * Should be invoked after the LFO is triggered.
124 * @param phase From 0 to 360 degrees.
125 */
126 void setPhase(float phase) {
127 if (phase < 0) phase = 0;
128 if (phase > 360) phase = 360;
129 phase /= 360.0f;
130 const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
131 unsigned int uiPhase = intLimit * phase + iLevel;
132 if (uiPhase > intLimit / 2) iLevel = uiPhase - intLimit;
133 else iLevel = uiPhase;
134 }
135
136 void setFrequency(float Frequency, unsigned int SampleRate) {
137 this->Frequency = Frequency;
138 const float freq = Frequency * this->ScriptFrequencyFactor;
139 const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
140 float r = freq / (float) SampleRate; // frequency alteration quotient
141 c = (int) (intLimit * r);
142 }
143
144 void setScriptDepthFactor(float factor, bool isFinal) {
145 this->ScriptDepthFactor = factor;
146 // set or reset this script depth parameter to be the sole
147 // source for the LFO depth
148 if (isFinal && !this->pFinalDepth)
149 this->pFinalDepth = &this->ScriptDepthFactor;
150 else if (!isFinal && this->pFinalDepth == &this->ScriptDepthFactor)
151 this->pFinalDepth = NULL;
152 // recalculate upon new depth
153 updateByMIDICtrlValue(this->ExtControlValue);
154 }
155
156 void setScriptFrequencyFactor(float factor, unsigned int SampleRate) {
157 this->ScriptFrequencyFactor = factor;
158 // in case script frequency was set as "final" value before,
159 // reset it so that all sources are processed from now on
160 if (this->pFinalFrequency == &this->ScriptFrequencyFactor)
161 this->pFinalFrequency = NULL;
162 // recalculate upon new frequency
163 setFrequency(this->Frequency, SampleRate);
164 }
165
166 void setScriptFrequencyFinal(float hz, unsigned int SampleRate) {
167 this->ScriptFrequencyFactor = hz;
168 // assign script's given frequency as sole source for the LFO
169 // frequency, thus ignore all other sources
170 if (!this->pFinalFrequency)
171 this->pFinalFrequency = &this->ScriptFrequencyFactor;
172 // recalculate upon new frequency
173 setFrequency(this->Frequency, SampleRate);
174 }
175
176 protected:
177 int iLevel;
178 int c;
179 float offset; ///< only needed for signed range
180 float normalizer;
181 };
182
183 } // namespace LinuxSampler
184
185 #endif // __LS_LFOTRIANGLEINTMATH_H__

  ViewVC Help
Powered by ViewVC