1 /***************************************************************************
2  *                                                                         *
3  *   LinuxSampler - modular, streaming capable sampler                     *
4  *                                                                         *
5  *   Copyright (C) 2011 - 2012 Grigor Iliev                                *
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 #ifndef __LS_SIGNALUNITRACK_H__
24 #define	__LS_SIGNALUNITRACK_H__
25 
26 #include "Event.h"
27 #include "SignalUnit.h"
28 #include "../../common/Pool.h"
29 
30 
31 namespace LinuxSampler {
32 
33     class EqSupport {
34         private:
35             int  BandCount;
36             int* GainIdxs; ///< the indices of the gain controls
37             int* FreqIdxs; ///< the indices of the frequency controls
38             int* BandwidthIdxs; ///< the indices of the bandwidth controls
39             Effect* pEffect;
40             Effect* pEffect2; // If the effect is mono we'll need two effects
41 
check(optional<float> minimum,optional<float> maximum,float value)42             inline float check(optional<float> minimum, optional<float> maximum, float value) {
43                 if (minimum) {
44                     float min = *minimum;
45                     if (value < min) value = min;
46                 }
47                 if (maximum) {
48                     float max = *maximum;
49                     if (value > max) value = max;
50                 }
51 
52                 return value;
53             }
54 
55         public:
56             EqSupport();
57             ~EqSupport();
58 
59             void PrintInfo();
60 
61             /**
62              * Searches for know EQ effects and create one if the search succeed.
63              * If the initialization is successful and EQ effect is selected,
64              * HasSupport() returns true;
65              */
66             void Install();
67 
68             void Uninstall();
69 
70             /** Returns true if an EQ is created and is ready for use. */
HasSupport()71             bool HasSupport() { return pEffect != NULL; }
72 
73             /** Reset the gains of all bands to 0dB. */
Reset()74             void Reset() {
75                 if (!HasSupport()) return;
76                 for (int i = 0; i < BandCount; i++) {
77                     pEffect->InputControl(GainIdxs[i])->SetValue(0); // 0dB
78                     if (pEffect2 != NULL) pEffect2->InputControl(GainIdxs[i])->SetValue(0); // 0dB
79                 }
80             }
81 
InitEffect(AudioOutputDevice * pDevice)82             void InitEffect(AudioOutputDevice* pDevice) {
83                 if (pEffect != NULL) pEffect->InitEffect(pDevice);
84                 if (pEffect2 != NULL) pEffect2->InitEffect(pDevice);
85             }
86 
GetBandCount()87             int GetBandCount() { return BandCount; }
88 
89             void SetGain(int band, float gain);
90             void SetFreq(int band, float freq);
91             void SetBandwidth(int band, float octaves);
92 
GetInChannelLeft()93             AudioChannel* GetInChannelLeft() {
94                 return pEffect->InputChannel(0);
95             }
96 
GetInChannelRight()97             AudioChannel* GetInChannelRight() {
98                 return pEffect2 != NULL ? pEffect2->InputChannel(0) : pEffect->InputChannel(1);
99             }
100 
GetOutChannelLeft()101             AudioChannel* GetOutChannelLeft() {
102                 return pEffect->OutputChannel(0);
103             }
104 
GetOutChannelRight()105             AudioChannel* GetOutChannelRight() {
106                 return pEffect2 != NULL ? pEffect2->OutputChannel(0) : pEffect->OutputChannel(1);
107             }
108 
RenderAudio(uint Samples)109             void RenderAudio(uint Samples) {
110                 pEffect->RenderAudio(Samples);
111                 if (pEffect2 != NULL) pEffect2->RenderAudio(Samples);
112             }
113     };
114 
115 
116 
117     class SignalUnitRack {
118         protected:
119             uint CurrentStep; // The current time step
120             bool bHasEq, releaseStageEntered;
121 
122         public:
123             FixedArray<SignalUnit*> Units; // A list of all signal units in this rack
124 
125             /**
126              * @param maxUnitCount We are using fixed size array because of the real-time safe requirements.
127              */
SignalUnitRack(int maxUnitCount)128             SignalUnitRack(int maxUnitCount): CurrentStep(0), bHasEq(false),
129                                               releaseStageEntered(false), Units(maxUnitCount) { }
130 
GetCurrentStep()131             uint GetCurrentStep() { return CurrentStep; }
132 
133             virtual EndpointSignalUnit* GetEndpointUnit() = 0;
134 
135             virtual void EnterFadeOutStage() = 0;
136             virtual void EnterFadeOutStage(int maxFadeOutSteps) = 0;
137 
138             /**
139              * Will be called to increment the time with one sample point.
140              * Each unit should recalculate its current level on every call of this function.
141              */
Increment()142             virtual void Increment() {
143                 CurrentStep++;
144 
145                 for (int i = 0; i < Units.size(); i++) {
146                     Units[i]->Increment();
147                 }
148             }
149 
ProcessCCEvent(RTList<Event>::Iterator & itEvent)150             virtual void ProcessCCEvent(RTList<Event>::Iterator& itEvent) {
151                 if ( !(itEvent->Type == Event::type_control_change && itEvent->Param.CC.Controller) ) return;
152                 for (int i = 0; i < Units.size(); i++) {
153                     Units[i]->ProcessCCEvent(itEvent->Param.CC.Controller, itEvent->Param.CC.Value);
154                 }
155             }
156 
157             /** Initializes and triggers the rack. */
Trigger()158             virtual void Trigger() {
159                 releaseStageEntered = false;
160                 CurrentStep = 0;
161                 for (int i = 0; i < Units.size(); i++) {
162                     Units[i]->Trigger();
163                 }
164             }
165 
166             /**
167              * When the rack belongs to a voice, this method is
168              * called when the voice enter the release stage.
169              */
EnterReleaseStage()170             virtual void EnterReleaseStage() {
171                 releaseStageEntered = true;
172                 for (int i = 0; i < Units.size(); i++) {
173                     Units[i]->EnterReleaseStage();
174                 }
175             }
176 
isReleaseStageEntered()177             bool isReleaseStageEntered() { return releaseStageEntered; }
178 
179             /**
180              * When the rack belongs to a voice, this method is
181              * called when the voice is of type which ignore note off.
182              */
CancelRelease()183             virtual void CancelRelease() {
184                 for (int i = 0; i < Units.size(); i++) {
185                     Units[i]->CancelRelease();
186                 }
187             }
188 
189             /**
190              * Determines whether an equalization is applied to the voice.
191              * Used for optimization.
192              */
HasEq()193             bool HasEq() { return bHasEq; }
194 
195             virtual void UpdateEqSettings(EqSupport* pEqSupport) = 0;
196     };
197 } // namespace LinuxSampler
198 
199 #endif	/* __LS_SIGNALUNITRACK_H__ */
200