Register update order: volume -> instrument -> effect -> key on
| 384 | |
| 385 | /// Register update order: volume -> instrument -> effect -> key on |
| 386 | void PlaybackManager::stepProcess() |
| 387 | { |
| 388 | clearDelayWithinStepCounts(); |
| 389 | updateDelayEventCounts(); |
| 390 | |
| 391 | auto& song = mod_.lock()->getSong(curSongNum_); |
| 392 | |
| 393 | // Store effects from the step to map |
| 394 | for (auto& attrib : songStyle_.trackAttribs) { |
| 395 | auto& step = song.getTrack(attrib.number) |
| 396 | .getPatternFromOrderNumber(playingPos_.order).getStep(playingPos_.step); |
| 397 | size_t uch = static_cast<size_t>(attrib.channelInSource); |
| 398 | effOnKeyOnMem_[attrib.source].at(uch).clear(); |
| 399 | directRegisterSets_[attrib.source].at(uch).clear(); |
| 400 | using storeFunc = void (PlaybackManager::*)(int, const Effect&); |
| 401 | static const std::unordered_map<SoundSource, storeFunc> storeEffectToMap = { |
| 402 | { SoundSource::FM, &PlaybackManager::storeEffectToMapFM }, |
| 403 | { SoundSource::SSG, &PlaybackManager::storeEffectToMapSSG }, |
| 404 | { SoundSource::RHYTHM, &PlaybackManager::storeEffectToMapRhythm }, |
| 405 | { SoundSource::ADPCM, &PlaybackManager::storeEffectToMapADPCM } |
| 406 | }; |
| 407 | for (int i = 0; i < Step::N_EFFECT; ++i) { |
| 408 | Effect&& eff = effect_utils::validateEffect(attrib.source, step.getEffect(i)); |
| 409 | (this->*storeEffectToMap.at(attrib.source))(attrib.channelInSource, eff); |
| 410 | } |
| 411 | } |
| 412 | |
| 413 | // Execute step events |
| 414 | bool isNextSet = executeStoredEffectsGlobal(); |
| 415 | const int countsInStep = tickCounter_.lock()->getCountsInCurrentStep(); |
| 416 | for (auto& attrib : songStyle_.trackAttribs) { |
| 417 | // Check whether it has been set note delay effect |
| 418 | size_t uch = static_cast<size_t>(attrib.channelInSource); |
| 419 | bool hasSetNoteDelay = false; |
| 420 | auto& mem = effOnStepBeginMem_[attrib.source].at(uch); |
| 421 | for (auto itr = mem.begin(); itr != mem.end(); ) { |
| 422 | if (itr->type == EffectType::NoteDelay) { |
| 423 | if (itr->value < countsInStep) { |
| 424 | hasSetNoteDelay = true; |
| 425 | } |
| 426 | else { |
| 427 | itr = mem.erase(itr); |
| 428 | continue; |
| 429 | } |
| 430 | } |
| 431 | ++itr; |
| 432 | } |
| 433 | |
| 434 | // |
| 435 | auto& step = song.getTrack(attrib.number) |
| 436 | .getPatternFromOrderNumber(playingPos_.order).getStep(playingPos_.step); |
| 437 | switch (attrib.source) { |
| 438 | case SoundSource::FM: |
| 439 | if (hasSetNoteDelay) { |
| 440 | // Set effect |
| 441 | executeStoredEffectsFM(attrib.channelInSource); |
| 442 | checkFMNoteDelayAndEnvelopeReset(step, attrib.channelInSource); |
| 443 | opnaCtrl_->tickEvent(SoundSource::FM, attrib.channelInSource); |
nothing calls this directly
no test coverage detected