/[svn]/linuxsampler/trunk/src/lfo.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/lfo.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 39 - (show annotations) (download)
Sun Mar 21 16:09:43 2004 UTC (20 years, 1 month ago) by schoenebeck
File size: 9351 byte(s)
* implemented all three low frequency oscillators (LFO1 = volume,
  LFO2 = filter cutoff frequency, LFO3 = pitch) for accurate .gig playback

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003 by Benno Senoner and Christian Schoenebeck *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #include "lfo.h"
24
25 LFO::LFO(ModulationSystem::destination_t ModulationDestination, manipulation_type_t ManipulationType, float Min, float Max, propagation_t Propagation, RTELMemoryPool<ModulationSystem::Event>* pEventPool) {
26 this->ModulationDestination = ModulationDestination;
27 this->ManipulationType = ManipulationType;
28 this->Propagation = Propagation;
29 this->pEvents = new RTEList<ModulationSystem::Event>(pEventPool);
30 this->ExtController = 0;
31 this->Min = Min;
32 this->Max = Max;
33 this->Range = Max - Min;
34 }
35
36 LFO::~LFO() {
37 if (pEvents) delete pEvents;
38 }
39
40 /**
41 * Will be called by the voice for every audio fragment to let the LFO write
42 * it's modulation changes to the synthesis parameter matrix for the current
43 * audio fragment.
44 *
45 * @param Samples - total number of sample points to be rendered in this
46 * audio fragment cycle by the audio engine
47 */
48 void LFO::Process(uint Samples) {
49 ModulationSystem::Event* pCtrlEvent = pEvents->first();
50
51 int iSample = TriggerDelay;
52 switch (ManipulationType) {
53 case manipulation_type_add: {
54 while (iSample < Samples) {
55 int process_break = Samples;
56 if (pCtrlEvent && pCtrlEvent->FragmentPos() <= process_break) process_break = pCtrlEvent->FragmentPos();
57
58 if (Coeff > 0.0f) { // level going up
59 while (iSample < process_break && Level <= CurrentMax) {
60 ModulationSystem::pDestinationParameter[ModulationDestination][iSample++] += Level;
61 Level += Coeff;
62 }
63 if (Level > CurrentMax) {
64 Coeff = -Coeff; // invert direction
65 Level += 2.0f * Coeff;
66 }
67 }
68 else if (Coeff < 0.0f) { // level going down
69 while (iSample < process_break && Level >= CurrentMin) {
70 ModulationSystem::pDestinationParameter[ModulationDestination][iSample++] += Level;
71 Level += Coeff;
72 }
73 if (Level < CurrentMin) {
74 Coeff = -Coeff; // invert direction
75 Level += 2.0f * Coeff;
76 }
77 }
78 else { // no modulation at all (Coeff = 0.0)
79 switch (Propagation) {
80 case propagation_top_down:
81 Level = Max;
82 break;
83 case propagation_middle_balanced:
84 Level = Min + 0.5f * Range;
85 break;
86 case propagation_bottom_up:
87 Level = Min;
88 break;
89 }
90 while (iSample < process_break) {
91 ModulationSystem::pDestinationParameter[ModulationDestination][iSample++] += Level;
92 }
93 }
94
95 if (pCtrlEvent) {
96 RecalculateCoeff(pCtrlEvent->Value);
97 pCtrlEvent = pEvents->next();
98 }
99 }
100 break;
101 }
102 case manipulation_type_multiply: {
103 while (iSample < Samples) {
104 int process_break = Samples;
105 if (pCtrlEvent && pCtrlEvent->FragmentPos() <= process_break) process_break = pCtrlEvent->FragmentPos();
106
107 if (Coeff > 0.0f) { // level going up
108 while (iSample < process_break && Level <= CurrentMax) {
109 ModulationSystem::pDestinationParameter[ModulationDestination][iSample++] *= Level;
110 Level += Coeff;
111 }
112 if (Level > CurrentMax) {
113 Coeff = -Coeff; // invert direction
114 Level += 2.0f * Coeff;
115 }
116 }
117 else if (Coeff < 0.0f) { // level going down
118 while (iSample < process_break && Level >= CurrentMin) {
119 ModulationSystem::pDestinationParameter[ModulationDestination][iSample++] *= Level;
120 Level += Coeff;
121 }
122 if (Level < CurrentMin) {
123 Coeff = -Coeff; // invert direction
124 Level += 2.0f * Coeff;
125 }
126 }
127 else { // no modulation at all (Coeff = 0.0)
128 switch (Propagation) {
129 case propagation_top_down:
130 Level = Max;
131 break;
132 case propagation_middle_balanced:
133 Level = Min + 0.5f * Range;
134 break;
135 case propagation_bottom_up:
136 Level = Min;
137 break;
138 }
139 while (iSample < process_break) {
140 ModulationSystem::pDestinationParameter[ModulationDestination][iSample++] *= Level;
141 }
142 }
143
144 if (pCtrlEvent) {
145 RecalculateCoeff(pCtrlEvent->Value);
146 pCtrlEvent = pEvents->next();
147 }
148 }
149 break;
150 }
151 }
152 TriggerDelay = 0;
153 pEvents->clear();
154 }
155
156 /**
157 * Will be called by the voice when the key / voice was triggered.
158 *
159 * @param Frequency - frequency of the oscillator in Hz
160 * @param InternalDepth - firm, internal oscillator amplitude
161 * @param ExtControlDepth - defines how strong the external MIDI controller
162 * has influence on the oscillator amplitude
163 * @param ExtControlValue - current MIDI value of the external controller
164 * for the time when the voice was triggered
165 * @param FlipPhase - inverts the oscillator wave
166 * @param Delay - number of sample points triggering should be
167 * delayed
168 */
169 void LFO::Trigger(float Frequency, uint16_t InternalDepth, uint16_t ExtControlDepth, uint16_t ExtControlValue, bool FlipPhase, uint Delay) {
170 this->Coeff = 0.0f;
171 this->InternalDepth = (InternalDepth / 1200.0f) * Range;
172 this->ExtControlDepthCoeff = (((float) ExtControlDepth / 1200.0f) / 127.0f) * Range;
173 this->TriggerDelay = Delay;
174 this->FrequencyCoeff = (2.0f * Frequency) / (float) ModulationSystem::SampleRate();
175
176 if (ExtController) RecalculateCoeff(ExtControlValue);
177 else RecalculateCoeff(0);
178
179 switch (Propagation) {
180 case propagation_top_down: {
181 if (FlipPhase) {
182 Level = CurrentMin;
183 }
184 else { // normal case
185 Level = Max;
186 Coeff = -Coeff; // level starts at max. thus has to go down now
187 }
188 break;
189 }
190 case propagation_middle_balanced: {
191 Level = Min + 0.5f * Range;
192 if (FlipPhase) Coeff = -Coeff; // invert direction (going down)
193 break;
194 }
195 case propagation_bottom_up: {
196 if (FlipPhase) {
197 Level = CurrentMax;
198 Coeff = -Coeff; // level starts at max. thus has to go down now
199 }
200 else { // normal case
201 Level = Min;
202 }
203 break;
204 }
205 }
206 }
207
208 /**
209 * Should always be called when the voice was killed.
210 */
211 void LFO::Reset() {
212 pEvents->clear();
213 }

  ViewVC Help
Powered by ViewVC