/[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 3561 - (show annotations) (download) (as text)
Fri Aug 23 11:44:00 2019 UTC (4 years, 8 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 8877 byte(s)
NKSP: Added standard units support for numbers and final "!" operator:

* NKSP strictness: Variable names, function names and preprocessor condition
  names must start with a regular character (a-z or A-Z); starting them with
  a digit or underscore is no longer allowed.

* NKSP parser fix: equal comparison operator "=" and not equal comparison
  operator "#" must only accept integer operands.

* NKSP language: Implemented support for standard units like Hertz, seconds,
  Bel including support for metric unit prefixes; so one can now e.g.
  conveniently use numbers in scripts like "5us" meaning "5 microseconds",
  or e.g. "12kHz" meaning "12 kilo Hertz", or e.g. "-14mdB" meaning
  "minus 14 Millidecibel", or e.g. "28c" meaning "28 cents" (for tuning).

* NKSP language: Introduced "final" operator "!" which is specifically
  intended for synthesis parameter values to denote that the synthesis
  parameter value is intended to be the "final" value for that synthesis
  parameter that should explicitly be used by the engine and thus causing
  the sampler engine to ignore all other modulation sources for the same
  synthesis parameter (like e.g. LFO, EG); by simply prefixing a value,
  variable or formula with this new "!" operator the expression is marked as
  being "final".

* Bumped version (2.1.1.svn4).

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<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 == 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 == 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, 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 == 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 start_level_max:
111 iLevel = (FlipPhase) ? 0 : intLimit >> 1;
112 break;
113 case start_level_mid:
114 if (FlipPhase) c = -c; // wave should go down
115 iLevel = intLimit >> 2;
116 break;
117 case start_level_min:
118 iLevel = (FlipPhase) ? intLimit >> 1 : 0;
119 break;
120 }
121 }
122
123 /**
124 * Should be invoked after the LFO is triggered.
125 * @param phase From 0 to 360 degrees.
126 */
127 void setPhase(float phase) {
128 if (phase < 0) phase = 0;
129 if (phase > 360) phase = 360;
130 phase /= 360.0f;
131 const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
132 unsigned int uiPhase = intLimit * phase + iLevel;
133 if (uiPhase > intLimit / 2) iLevel = uiPhase - intLimit;
134 else iLevel = uiPhase;
135 }
136
137 void setFrequency(float Frequency, unsigned int SampleRate) {
138 this->Frequency = Frequency;
139 const float freq = Frequency * this->ScriptFrequencyFactor;
140 const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
141 float r = freq / (float) SampleRate; // frequency alteration quotient
142 c = (int) (intLimit * r);
143 }
144
145 void setScriptDepthFactor(float factor, bool isFinal) {
146 this->ScriptDepthFactor = factor;
147 // set or reset this script depth parameter to be the sole
148 // source for the LFO depth
149 if (isFinal && !this->pFinalDepth)
150 this->pFinalDepth = &this->ScriptDepthFactor;
151 else if (!isFinal && this->pFinalDepth == &this->ScriptDepthFactor)
152 this->pFinalDepth = NULL;
153 // recalculate upon new depth
154 updateByMIDICtrlValue(this->ExtControlValue);
155 }
156
157 void setScriptFrequencyFactor(float factor, unsigned int SampleRate) {
158 this->ScriptFrequencyFactor = factor;
159 // in case script frequency was set as "final" value before,
160 // reset it so that all sources are processed from now on
161 if (this->pFinalFrequency == &this->ScriptFrequencyFactor)
162 this->pFinalFrequency = NULL;
163 // recalculate upon new frequency
164 setFrequency(this->Frequency, SampleRate);
165 }
166
167 void setScriptFrequencyFinal(float hz, unsigned int SampleRate) {
168 this->ScriptFrequencyFactor = hz;
169 // assign script's given frequency as sole source for the LFO
170 // frequency, thus ignore all other sources
171 if (!this->pFinalFrequency)
172 this->pFinalFrequency = &this->ScriptFrequencyFactor;
173 // recalculate upon new frequency
174 setFrequency(this->Frequency, SampleRate);
175 }
176
177 protected:
178 int iLevel;
179 int c;
180 float offset; ///< only needed for signed range
181 float normalizer;
182 };
183
184 } // namespace LinuxSampler
185
186 #endif // __LS_LFOTRIANGLEINTMATH_H__

  ViewVC Help
Powered by ViewVC