Steps a single frame */
| 274 | /** Steps a single frame |
| 275 | */ |
| 276 | static void Engine_stepFrame(Engine* that) { |
| 277 | Engine::Internal* internal = that->internal; |
| 278 | |
| 279 | // Param smoothing |
| 280 | Module* smoothModule = internal->smoothModule; |
| 281 | if (smoothModule) { |
| 282 | int smoothParamId = internal->smoothParamId; |
| 283 | float smoothValue = internal->smoothValue; |
| 284 | Param* smoothParam = &smoothModule->params[smoothParamId]; |
| 285 | float value = smoothParam->value; |
| 286 | float newValue; |
| 287 | if (internal->remoteDetails != nullptr && internal->remoteDetails->connected) { |
| 288 | newValue = value; |
| 289 | sendParamChangeToRemote(internal->remoteDetails, smoothModule->id, smoothParamId, value); |
| 290 | } else { |
| 291 | // Use decay rate of roughly 1 graphics frame |
| 292 | const float smoothLambda = 60.f; |
| 293 | newValue = value + (smoothValue - value) * smoothLambda * internal->sampleTime; |
| 294 | } |
| 295 | if (d_isEqual(value, newValue)) { |
| 296 | // Snap to actual smooth value if the value doesn't change enough (due to the granularity of floats) |
| 297 | smoothParam->setValue(smoothValue); |
| 298 | internal->smoothModule = NULL; |
| 299 | internal->smoothParamId = 0; |
| 300 | } |
| 301 | else { |
| 302 | smoothParam->setValue(newValue); |
| 303 | } |
| 304 | } |
| 305 | |
| 306 | // Flip messages for each module |
| 307 | for (Module* module : internal->modules) { |
| 308 | if (module->leftExpander.messageFlipRequested) { |
| 309 | std::swap(module->leftExpander.producerMessage, module->leftExpander.consumerMessage); |
| 310 | module->leftExpander.messageFlipRequested = false; |
| 311 | } |
| 312 | if (module->rightExpander.messageFlipRequested) { |
| 313 | std::swap(module->rightExpander.producerMessage, module->rightExpander.consumerMessage); |
| 314 | module->rightExpander.messageFlipRequested = false; |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | // Build ProcessArgs |
| 319 | Module::ProcessArgs processArgs; |
| 320 | processArgs.sampleRate = internal->sampleRate; |
| 321 | processArgs.sampleTime = internal->sampleTime; |
| 322 | processArgs.frame = internal->frame; |
| 323 | |
| 324 | // Process terminal inputs first |
| 325 | for (TerminalModule* terminalModule : internal->terminalModules) { |
| 326 | TerminalModule__doProcess(terminalModule, processArgs, true); |
| 327 | } |
| 328 | |
| 329 | // Step each module and cables |
| 330 | for (Module* module : internal->modules) { |
| 331 | Module__doProcess(module, processArgs); |
| 332 | for (Output& output : module->outputs) { |
| 333 | for (Cable* cable : output.cables) |
no test coverage detected