| 236 | } |
| 237 | |
| 238 | void ConvolverNode::process(ContextRenderLock & r, int bufferSize) |
| 239 | { |
| 240 | if (_swap_ready) { |
| 241 | // this could cause an audio hiccough when swapping, but it's necessary to avoid a race |
| 242 | std::unique_lock<std::mutex> kernel_guard(_kernel_mutex); |
| 243 | _swap_ready = false; |
| 244 | std::swap(_kernels, _pending_kernels); |
| 245 | _pending_kernels.clear(); |
| 246 | } |
| 247 | |
| 248 | AudioBus * outputBus = output(0)->bus(r); |
| 249 | AudioBus * inputBus = input(0)->bus(r); |
| 250 | |
| 251 | if (!isInitialized() || !outputBus || !inputBus || !inputBus->numberOfChannels() || !_kernels.size()) |
| 252 | { |
| 253 | outputBus->zero(); |
| 254 | return; |
| 255 | } |
| 256 | |
| 257 | // if the user never specified the number of output channels, make it match the input |
| 258 | if (!outputBus->numberOfChannels()) |
| 259 | { |
| 260 | output(0)->setNumberOfChannels(r, inputBus->numberOfChannels()); |
| 261 | outputBus = output(0)->bus(r); // set number of channels invalidates the pointer |
| 262 | } |
| 263 | |
| 264 | int quantumFrameOffset = _scheduler._renderOffset; |
| 265 | int nonSilentFramesToProcess = _scheduler._renderLength; |
| 266 | |
| 267 | int numInputChannels = static_cast<int>(inputBus->numberOfChannels()); |
| 268 | int numOutputChannels = static_cast<int>(outputBus->numberOfChannels()); |
| 269 | int numReverbChannels = static_cast<int>(_kernels.size()); |
| 270 | |
| 271 | if (!nonSilentFramesToProcess) |
| 272 | { |
| 273 | outputBus->zero(); |
| 274 | return; |
| 275 | } |
| 276 | |
| 277 | /// @todo should a situation such as 1:2:1 be invalid, or should it be powersum(1:1:1, 1:2:1)? |
| 278 | /// at the moment, this routine trivially does 1:1:1 only. |
| 279 | |
| 280 | for (int i = 0; i < numOutputChannels; ++i) |
| 281 | { |
| 282 | int kernel = i < numReverbChannels ? i : numReverbChannels - 1; |
| 283 | lab::sp_conv * conv = _kernels[kernel].conv; |
| 284 | float* destP = outputBus->channel(i)->mutableData() + _scheduler._renderOffset; |
| 285 | |
| 286 | // Start rendering at the correct offset. |
| 287 | destP += quantumFrameOffset; |
| 288 | { |
| 289 | AudioBus * input_bus = input(0)->bus(r); |
| 290 | int in_channel = i < numInputChannels ? i : numInputChannels - 1; |
| 291 | float const* data = input_bus->channel(in_channel)->data() + quantumFrameOffset; |
| 292 | size_t c = input_bus->channel(in_channel)->length(); |
| 293 | for (int j = 0; j < _scheduler._renderLength; ++j) |
| 294 | { |
| 295 | lab::SPFLOAT in = j < c ? data[j] : 0.f; // don't read off the end of the input buffer |
nothing calls this directly
no test coverage detected