| 116 | } |
| 117 | |
| 118 | void EffectChain::Process(double time) |
| 119 | { |
| 120 | IAudioReceiver* target = GetTarget(); |
| 121 | |
| 122 | if (target == nullptr) |
| 123 | return; |
| 124 | |
| 125 | ComputeSliders(0); |
| 126 | SyncBuffers(); |
| 127 | mDryBuffer.SetNumActiveChannels(GetBuffer()->NumActiveChannels()); |
| 128 | |
| 129 | int bufferSize = GetBuffer()->BufferSize(); |
| 130 | |
| 131 | if (mEnabled) |
| 132 | { |
| 133 | mEffectMutex.lock(); |
| 134 | |
| 135 | for (int i = 0; i < mEffects.size(); ++i) |
| 136 | { |
| 137 | mDryBuffer.CopyFrom(GetBuffer()); |
| 138 | |
| 139 | mEffects[i]->ProcessAudio(time, GetBuffer()); |
| 140 | |
| 141 | float* dryWetBuffer = gWorkBuffer; |
| 142 | float* invDryWetBuffer = gWorkBuffer + bufferSize; |
| 143 | for (int j = 0; j < bufferSize; ++j) |
| 144 | { |
| 145 | ComputeSliders(j); |
| 146 | dryWetBuffer[j] = mDryWetLevels[i]; |
| 147 | invDryWetBuffer[j] = 1.0f - mDryWetLevels[i]; |
| 148 | } |
| 149 | |
| 150 | for (int ch = 0; ch < GetBuffer()->NumActiveChannels(); ++ch) |
| 151 | { |
| 152 | Mult(mDryBuffer.GetChannel(ch), invDryWetBuffer, bufferSize); |
| 153 | Mult(GetBuffer()->GetChannel(ch), dryWetBuffer, bufferSize); |
| 154 | Add(GetBuffer()->GetChannel(ch), mDryBuffer.GetChannel(ch), bufferSize); |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | mEffectMutex.unlock(); |
| 159 | } |
| 160 | |
| 161 | for (int ch = 0; ch < GetBuffer()->NumActiveChannels(); ++ch) |
| 162 | { |
| 163 | float* buffer = GetBuffer()->GetChannel(ch); |
| 164 | float volSq = mVolume * mVolume; |
| 165 | for (int i = 0; i < bufferSize; ++i) |
| 166 | buffer[i] *= volSq; |
| 167 | Add(target->GetBuffer()->GetChannel(ch), buffer, bufferSize); |
| 168 | GetVizBuffer()->WriteChunk(buffer, bufferSize, ch); |
| 169 | } |
| 170 | |
| 171 | GetBuffer()->Reset(); |
| 172 | } |
| 173 | |
| 174 | void EffectChain::Poll() |
| 175 | { |
nothing calls this directly
no test coverage detected