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

Contents of /linuxsampler/trunk/src/engines/common/LFOSine.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: 6863 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 * Copyright (c) 2019 Christian Schoenebeck
3 *
4 * http://www.linuxsampler.org
5 *
6 * This file is part of LinuxSampler and released under the same terms.
7 * See README file for details.
8 */
9
10 #ifndef LS_LFOSINE_H
11 #define LS_LFOSINE_H
12
13 #include "LFOBase.h"
14
15 namespace LinuxSampler {
16
17 /** @brief Sine LFO (numeric, complex nr implementation)
18 *
19 * This is a Sinus Low Frequency Oscillator implementation using a complex
20 * number with numeric (descrete) math as basis for its oscillation.
21 */
22 template<LFO::range_type_t RANGE>
23 class LFOSine : public LFOBase<RANGE> {
24 public:
25
26 /**
27 * Constructor
28 *
29 * @param Max - maximum value of the output levels
30 */
31 LFOSine(float Max) : LFOBase<RANGE>::LFOBase(Max) {
32 }
33
34 /**
35 * Calculates exactly one sample point of the LFO wave.
36 *
37 * @returns next LFO level
38 */
39 inline float render() {
40 real -= c * imag;
41 imag += c * real;
42 if (RANGE == LFO::range_unsigned)
43 return real * normalizer + offset;
44 else /* signed range */
45 return real * normalizer;
46 }
47
48 /**
49 * Update LFO depth with a new external controller value.
50 *
51 * @param ExtControlValue - new external controller value
52 */
53 inline void updateByMIDICtrlValue(const uint16_t& ExtControlValue) {
54 this->ExtControlValue = ExtControlValue;
55
56 const float max = (this->InternalDepth + ExtControlValue * this->ExtControlDepthCoeff) * this->ScriptDepthFactor;
57 if (RANGE == LFO::range_unsigned) {
58 normalizer = max * 0.5f;
59 offset = normalizer;
60 } else { // signed range
61 normalizer = max;
62 }
63 }
64
65 /**
66 * Will be called by the voice when the key / voice was triggered.
67 *
68 * @param Frequency - frequency of the oscillator in Hz
69 * @param StartLevel - on which level the wave should start
70 * @param InternalDepth - firm, internal oscillator amplitude
71 * @param ExtControlDepth - defines how strong the external MIDI
72 * controller has influence on the
73 * oscillator amplitude
74 * @param FlipPhase - inverts the oscillator wave against
75 * a horizontal axis
76 * @param SampleRate - current sample rate of the engines
77 * audio output signal
78 */
79 void trigger(float Frequency, LFO::start_level_t StartLevel, uint16_t InternalDepth, uint16_t ExtControlDepth, bool FlipPhase, unsigned int SampleRate) {
80 this->Frequency = Frequency;
81 this->ScriptFrequencyFactor = this->ScriptDepthFactor = 1.f; // reset for new voice
82 this->InternalDepth = (InternalDepth / 1200.0f) * this->Max;
83 this->ExtControlDepthCoeff = (((float) ExtControlDepth / 1200.0f) / 127.0f) * this->Max;
84 this->pFinalDepth = NULL;
85 this->pFinalFrequency = NULL;
86
87 const float freq = Frequency * this->ScriptFrequencyFactor;
88 c = 2.0f * M_PI * freq / (float) SampleRate;
89
90 switch (StartLevel) {
91 case LFO::start_level_mid:
92 this->startPhase = (FlipPhase) ? 0.5 * M_PI : 1.5 * M_PI; // 90� or 270�
93 break;
94 case LFO::start_level_max:
95 this->startPhase = (FlipPhase) ? M_PI : 0.0; // 180� or 0�
96 break;
97 case LFO::start_level_min:
98 this->startPhase = (FlipPhase) ? 0.0 : M_PI; // 0� or 180�
99 break;
100 }
101 real = cos(this->startPhase);
102 imag = sin(this->startPhase);
103 }
104
105 /**
106 * Should be invoked after the LFO is triggered with StartLevel
107 * start_level_min.
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 = phase / 360.0f * 2 * M_PI;
114 real = cos(this->startPhase + phase);
115 imag = sin(this->startPhase + phase);
116 }
117
118 void setFrequency(float Frequency, unsigned int SampleRate) {
119 this->Frequency = Frequency;
120 const float freq = Frequency * this->ScriptFrequencyFactor;
121 c = 2.0f * M_PI * freq / (float) SampleRate;
122 }
123
124 void setScriptDepthFactor(float factor, bool isFinal) {
125 this->ScriptDepthFactor = factor;
126 // set or reset this script depth parameter to be the sole
127 // source for the LFO depth
128 if (isFinal && !this->pFinalDepth)
129 this->pFinalDepth = &this->ScriptDepthFactor;
130 else if (!isFinal && this->pFinalDepth == &this->ScriptDepthFactor)
131 this->pFinalDepth = NULL;
132 // recalculate upon new depth
133 updateByMIDICtrlValue(this->ExtControlValue);
134 }
135
136 void setScriptFrequencyFactor(float factor, unsigned int SampleRate) {
137 this->ScriptFrequencyFactor = factor;
138 // in case script frequency was set as "final" value before,
139 // reset it so that all sources are processed from now on
140 if (this->pFinalFrequency == &this->ScriptFrequencyFactor)
141 this->pFinalFrequency = NULL;
142 // recalculate upon new frequency
143 setFrequency(this->Frequency, SampleRate);
144 }
145
146 void setScriptFrequencyFinal(float hz, unsigned int SampleRate) {
147 this->ScriptFrequencyFactor = hz;
148 // assign script's given frequency as sole source for the LFO
149 // frequency, thus ignore all other sources
150 if (!this->pFinalFrequency)
151 this->pFinalFrequency = &this->ScriptFrequencyFactor;
152 // recalculate upon new frequency
153 setFrequency(this->Frequency, SampleRate);
154 }
155
156 private:
157 float c;
158 float real;
159 float imag;
160 float normalizer;
161 float offset;
162 double startPhase;
163 };
164
165 } // namespace LinuxSampler
166
167 #endif // LS_LFOSINE_H

  ViewVC Help
Powered by ViewVC