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

Contents of /linuxsampler/trunk/src/engines/common/PulseLFO.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, 7 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 8154 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 Christian Schoenebeck *
4 * Copyright (C) 2011 Christian Schoenebeck and Grigor Iliev *
5 * *
6 * This library is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This library is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this library; if not, write to the Free Software *
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
19 * MA 02111-1307 USA *
20 ***************************************************************************/
21
22 #ifndef __LS_PULSELFO_H__
23 #define __LS_PULSELFO_H__
24
25 #include "LFOBase.h"
26
27 namespace LinuxSampler {
28
29 /** @brief Pulse LFO (int math implementation)
30 *
31 * This is a pulse Low Frequency Oscillator which uses pure integer
32 * math (without branches) to synthesize the pulse wave.
33 */
34 template<range_type_t RANGE, int WIDTH /* in permilles */>
35 class PulseLFO : public LFOBase<RANGE> {
36 public:
37
38 /**
39 * Constructor
40 *
41 * @param Max - maximum value of the output levels
42 */
43 PulseLFO(float Max) : LFOBase<RANGE>::LFOBase(Max) {
44 }
45
46 /**
47 * Calculates exactly one sample point of the LFO wave.
48 *
49 * @returns next LFO level
50 */
51 inline float render() {
52 uiLevel += c;
53 if (RANGE == range_unsigned)
54 return uiLevel <= width ? normalizer : 0;
55 else /* signed range */
56 return uiLevel <= width ? normalizer : -normalizer;
57 }
58
59 /**
60 * Update LFO depth with a new external controller value.
61 *
62 * @param ExtControlValue - new external controller value
63 */
64 inline void updateByMIDICtrlValue(const uint16_t& ExtControlValue) {
65 this->ExtControlValue = ExtControlValue;
66
67 const float max = (this->InternalDepth + ExtControlValue * this->ExtControlDepthCoeff) * this->ScriptDepthFactor;
68 normalizer = max;
69 }
70
71 /**
72 * Will be called by the voice when the key / voice was triggered.
73 *
74 * @param Frequency - frequency of the oscillator in Hz
75 * @param InternalDepth - firm, internal oscillator amplitude
76 * @param ExtControlDepth - defines how strong the external MIDI
77 * controller has influence on the
78 * oscillator amplitude
79 * @param FlipPhase - inverts the oscillator wave against
80 * a horizontal axis
81 * @param SampleRate - current sample rate of the engines
82 * audio output signal
83 * @param PulseWidth - the pulse width in percents
84 */
85 void trigger(float Frequency, uint16_t InternalDepth, uint16_t ExtControlDepth, float PulseWidth, unsigned int SampleRate) {
86 this->Frequency = Frequency;
87 this->InternalDepth = (InternalDepth / 1200.0f) * this->Max;
88 this->ExtControlDepthCoeff = (((float) ExtControlDepth / 1200.0f) / 127.0f) * this->Max;
89 this->ScriptFrequencyFactor = this->ScriptDepthFactor = 1.f; // reset for new voice
90 this->pFinalDepth = NULL;
91 this->pFinalFrequency = NULL;
92
93 const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
94 const float freq = Frequency * this->ScriptFrequencyFactor;
95 const float r = freq / (float) SampleRate; // frequency alteration quotient
96 c = (int) (intLimit * r);
97 width = (PulseWidth / 100.0) * intLimit;
98
99 uiLevel = 0;
100 }
101
102 virtual void trigger(float Frequency, start_level_t StartLevel, uint16_t InternalDepth, uint16_t ExtControlDepth, bool FlipPhase, unsigned int SampleRate) {
103 trigger(Frequency, InternalDepth, ExtControlDepth, WIDTH / 10.0f, SampleRate);
104 }
105
106 /**
107 * Should be invoked after the LFO is triggered.
108 * @param phase From 0 to 360 degrees.
109 */
110 void setPhase(float phase) {
111 if (phase < 0) phase = 0;
112 if (phase > 360) phase = 360;
113 phase /= 360.0f;
114 const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
115 uiLevel = intLimit * phase;
116 }
117
118 void setFrequency(float Frequency, unsigned int SampleRate) {
119 this->Frequency = Frequency;
120 const float freq = Frequency * this->ScriptFrequencyFactor;
121 const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
122 float r = freq / (float) SampleRate; // frequency alteration quotient
123 c = (int) (intLimit * r);
124 }
125
126 void setScriptDepthFactor(float factor, bool isFinal) {
127 this->ScriptDepthFactor = factor;
128 // set or reset this script depth parameter to be the sole
129 // source for the LFO depth
130 if (isFinal && !this->pFinalDepth)
131 this->pFinalDepth = &this->ScriptDepthFactor;
132 else if (!isFinal && this->pFinalDepth == &this->ScriptDepthFactor)
133 this->pFinalDepth = NULL;
134 // recalculate upon new depth
135 updateByMIDICtrlValue(this->ExtControlValue);
136 }
137
138 void setScriptFrequencyFactor(float factor, unsigned int SampleRate) {
139 this->ScriptFrequencyFactor = factor;
140 // in case script frequency was set as "final" value before,
141 // reset it so that all sources are processed from now on
142 if (this->pFinalFrequency == &this->ScriptFrequencyFactor)
143 this->pFinalFrequency = NULL;
144 // recalculate upon new frequency
145 setFrequency(this->Frequency, SampleRate);
146 }
147
148 void setScriptFrequencyFinal(float hz, unsigned int SampleRate) {
149 this->ScriptFrequencyFactor = hz;
150 // assign script's given frequency as sole source for the LFO
151 // frequency, thus ignore all other sources
152 if (!this->pFinalFrequency)
153 this->pFinalFrequency = &this->ScriptFrequencyFactor;
154 // recalculate upon new frequency
155 setFrequency(this->Frequency, SampleRate);
156 }
157
158 protected:
159 unsigned int uiLevel;
160 unsigned int width;
161 int c;
162 float normalizer;
163 };
164
165 template<range_type_t RANGE>
166 class SquareLFO : public PulseLFO<RANGE, 500> {
167 public:
168 SquareLFO(float Max) : PulseLFO<RANGE, 500>::PulseLFO(Max) { }
169 };
170
171 } // namespace LinuxSampler
172
173 #endif // __LS_PULSELFO_H__

  ViewVC Help
Powered by ViewVC