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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3561 - (hide annotations) (download) (as text)
Fri Aug 23 11:44:00 2019 UTC (4 years, 8 months ago) by schoenebeck
Original Path: linuxsampler/trunk/src/engines/common/PulseLFO.h
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 iliev 2223 /***************************************************************************
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 schoenebeck 3118 inline void updateByMIDICtrlValue(const uint16_t& ExtControlValue) {
65     this->ExtControlValue = ExtControlValue;
66    
67     const float max = (this->InternalDepth + ExtControlValue * this->ExtControlDepthCoeff) * this->ScriptDepthFactor;
68 iliev 2223 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 schoenebeck 3118 this->Frequency = Frequency;
87 iliev 2223 this->InternalDepth = (InternalDepth / 1200.0f) * this->Max;
88     this->ExtControlDepthCoeff = (((float) ExtControlDepth / 1200.0f) / 127.0f) * this->Max;
89 schoenebeck 3118 this->ScriptFrequencyFactor = this->ScriptDepthFactor = 1.f; // reset for new voice
90 schoenebeck 3561 this->pFinalDepth = NULL;
91     this->pFinalFrequency = NULL;
92 iliev 2223
93     const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
94 schoenebeck 3118 const float freq = Frequency * this->ScriptFrequencyFactor;
95     const float r = freq / (float) SampleRate; // frequency alteration quotient
96 iliev 2223 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 iliev 2225
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 iliev 2227
118     void setFrequency(float Frequency, unsigned int SampleRate) {
119 schoenebeck 3118 this->Frequency = Frequency;
120     const float freq = Frequency * this->ScriptFrequencyFactor;
121 iliev 2227 const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
122 schoenebeck 3118 float r = freq / (float) SampleRate; // frequency alteration quotient
123 iliev 2227 c = (int) (intLimit * r);
124     }
125 iliev 2223
126 schoenebeck 3561 void setScriptDepthFactor(float factor, bool isFinal) {
127 schoenebeck 3118 this->ScriptDepthFactor = factor;
128 schoenebeck 3561 // 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 schoenebeck 3118 updateByMIDICtrlValue(this->ExtControlValue);
136     }
137    
138     void setScriptFrequencyFactor(float factor, unsigned int SampleRate) {
139     this->ScriptFrequencyFactor = factor;
140 schoenebeck 3561 // 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 schoenebeck 3118 setFrequency(this->Frequency, SampleRate);
146     }
147    
148 schoenebeck 3561 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 iliev 2223 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