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