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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3612 - (hide annotations) (download) (as text)
Mon Sep 30 18:03:43 2019 UTC (4 years, 6 months ago) by schoenebeck
Original Path: linuxsampler/trunk/src/engines/common/LFOSawIntMath.h
File MIME type: text/x-c++hdr
File size: 7804 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 schoenebeck 3612 /*
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_LFOSAWINTMATH_H
11     #define LS_LFOSAWINTMATH_H
12    
13     #include <stdlib.h>
14     #include "LFOBase.h"
15    
16     namespace LinuxSampler {
17    
18     /** @brief Saw LFO (int math implementation)
19     *
20     * This is a Saw Low Frequency Oscillator which uses pure integer
21     * math (without branches) to synthesize the saw wave.
22     */
23     template<LFO::range_type_t RANGE>
24     class LFOSawIntMath : public LFOBase<RANGE> {
25     public:
26     /**
27     * Constructor
28     *
29     * @param Max - maximum value of the output levels
30     */
31     LFOSawIntMath(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     this->slope += this->c;
41     if (RANGE == LFO::range_unsigned)
42     return this->denormalizer * float(this->slope);
43     else // signed range
44     return this->denormalizer * float(int(this->slope) + this->offset);
45     }
46    
47     /**
48     * Update LFO depth with a new external controller value.
49     *
50     * @param ExtControlValue - new external controller value
51     */
52     inline void updateByMIDICtrlValue(const uint16_t& ExtControlValue) {
53     this->ExtControlValue = ExtControlValue;
54    
55     const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
56     const float max = (this->InternalDepth + ExtControlValue * this->ExtControlDepthCoeff) * this->ScriptDepthFactor;
57     if (RANGE == LFO::range_unsigned) {
58     denormalizer = max / (float) intLimit / 2.0;
59     } else { // signed range
60     denormalizer = max / (float) intLimit * 2.0;
61     offset = -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->InternalDepth = (InternalDepth / 1200.0f) * this->Max;
82     this->ExtControlDepthCoeff = (((float) ExtControlDepth / 1200.0f) / 127.0f) * this->Max;
83     this->ScriptFrequencyFactor = this->ScriptDepthFactor = 1.f; // reset for new voice
84     if (RANGE == LFO::range_unsigned) {
85     this->InternalDepth *= 2.0f;
86     this->ExtControlDepthCoeff *= 2.0f;
87     }
88     this->pFinalDepth = NULL;
89     this->pFinalFrequency = NULL;
90    
91     this->flipPhaseFactor = FlipPhase ? -1 : 1;
92     const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
93     const float freq = Frequency * this->ScriptFrequencyFactor;
94     const float r = freq / (float) SampleRate; // frequency alteration quotient
95     c = int(intLimit * r * this->flipPhaseFactor);
96    
97     const int slopeAtMid = (RANGE == LFO::range_unsigned) ? intLimit / 2 : intLimit;
98     const int slopeAtMin = (RANGE == LFO::range_unsigned) ? intLimit : intLimit / 2;
99    
100     switch (StartLevel) {
101     case LFO::start_level_mid:
102     //slope = (FlipPhase) ? slopeAtMin : slopeAtMid;
103     slope = slopeAtMid;
104     break;
105    
106     // with saw function, min and max are actually always the same thing
107     // (and no matter if FlipPhase or not)
108     case LFO::start_level_max:
109     case LFO::start_level_min:
110     slope = slopeAtMin;
111     break;
112     }
113     }
114    
115     /**
116     * Should be invoked after the LFO is triggered.
117     * @param phase From 0 to 360 degrees.
118     */
119     void setPhase(float phase) {
120     if (phase < 0) phase = 0;
121     if (phase > 360) phase = 360;
122     phase /= 360.0f;
123     const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
124     slope += intLimit * phase * flipPhaseFactor;
125     }
126    
127     void setFrequency(float Frequency, unsigned int SampleRate) {
128     this->Frequency = Frequency;
129     const float freq = Frequency * this->ScriptFrequencyFactor;
130     const unsigned int intLimit = (unsigned int) -1; // all 0xFFFF...
131     float r = freq / (float) SampleRate; // frequency alteration quotient
132     c = int(intLimit * r * this->flipPhaseFactor);
133     }
134    
135     void setScriptDepthFactor(float factor, bool isFinal) {
136     this->ScriptDepthFactor = factor;
137     // set or reset this script depth parameter to be the sole
138     // source for the LFO depth
139     if (isFinal && !this->pFinalDepth)
140     this->pFinalDepth = &this->ScriptDepthFactor;
141     else if (!isFinal && this->pFinalDepth == &this->ScriptDepthFactor)
142     this->pFinalDepth = NULL;
143     // recalculate upon new depth
144     updateByMIDICtrlValue(this->ExtControlValue);
145     }
146    
147     void setScriptFrequencyFactor(float factor, unsigned int SampleRate) {
148     this->ScriptFrequencyFactor = factor;
149     // in case script frequency was set as "final" value before,
150     // reset it so that all sources are processed from now on
151     if (this->pFinalFrequency == &this->ScriptFrequencyFactor)
152     this->pFinalFrequency = NULL;
153     // recalculate upon new frequency
154     setFrequency(this->Frequency, SampleRate);
155     }
156    
157     void setScriptFrequencyFinal(float hz, unsigned int SampleRate) {
158     this->ScriptFrequencyFactor = hz;
159     // assign script's given frequency as sole source for the LFO
160     // frequency, thus ignore all other sources
161     if (!this->pFinalFrequency)
162     this->pFinalFrequency = &this->ScriptFrequencyFactor;
163     // recalculate upon new frequency
164     setFrequency(this->Frequency, SampleRate);
165     }
166    
167     protected:
168     unsigned int slope;
169     unsigned int c;
170     float offset; ///< only needed for signed range
171     float denormalizer;
172     float flipPhaseFactor; ///< Factor instead of boolean to avoid branches.
173     };
174    
175     } // namespace LinuxSampler
176    
177     #endif // LS_LFOSAWINTMATH_H

  ViewVC Help
Powered by ViewVC