diff --git a/soh/soh/Enhancements/accessible-actors/SfxExtractor.cpp b/soh/soh/Enhancements/accessible-actors/SfxExtractor.cpp index 66bd3f2cf..95cfc1cb8 100644 --- a/soh/soh/Enhancements/accessible-actors/SfxExtractor.cpp +++ b/soh/soh/Enhancements/accessible-actors/SfxExtractor.cpp @@ -13,26 +13,29 @@ void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples); extern bool freezeGame; } -bool SfxExtractor::isAllZero(int16_t* buffer, size_t count) { +bool SfxExtractor::isAllSilence(int16_t* buffer, size_t count) { for (size_t i = 0; i < count; i++) { - if (buffer[i] != 0) + if (!isSilentSample(buffer[i]))//Tolerance for low-amplitude dither noise. return false; } return true; } +bool SfxExtractor::isSilentSample(int16_t sample) { + return abs(sample) <= SFX_EXTRACTION_SILENCE_THRESHOLD; + +} // Find the beginning of a captured signal. size_t SfxExtractor::adjustedStartOfInput() { size_t startOfInput = 0; - while (startOfInput + 2 < SFX_EXTRACTION_BUFFER_SIZE * 2 && - (tempBuffer[startOfInput] == 0 || tempBuffer[startOfInput + 1] == 0)) { + while (startOfInput + 2 < SFX_EXTRACTION_BUFFER_SIZE * 2 && isSilentSample(tempBuffer[startOfInput]) && isSilentSample(tempBuffer[startOfInput + 1])) { startOfInput += 2; } return startOfInput; } size_t SfxExtractor::adjustedEndOfInput(size_t endOfInput) { - while (endOfInput > 0 && (tempBuffer[endOfInput] == 0 || tempBuffer[endOfInput - 1] == 0)) { + while (endOfInput > 0 && (!isSilentSample(tempBuffer[endOfInput]) || isSilentSample(tempBuffer[endOfInput - 1]))) { endOfInput -= 2; } return endOfInput; @@ -82,6 +85,7 @@ void SfxExtractor::setup() { } sfxToRip = 0; + currentSfx = -1; currentStep = STEP_MAIN; archive = std::make_shared(sohAccessibilityPath); archive->Open(); @@ -89,11 +93,11 @@ void SfxExtractor::setup() { } void SfxExtractor::ripNextSfx() { - { - auto lock = OTRAudio_Lock(); + //This entire method is expected to be atomic; Don't try to narrow the scope of this lock please! + //Todo: remove the thread altogether as we don't actually need or want parallelism here. +auto lock = OTRAudio_Lock(); if (captureThreadState == CT_READY || captureThreadState == CT_PRIMING) return; // Keep going. - } // Was the last sfx a loop? If so then we need to stop it, and then we need to run audio out to nowhere for as long // as it takes to get back to a blank slate. if (currentSfx != -1) { @@ -111,11 +115,7 @@ void SfxExtractor::ripNextSfx() { currentSfx = sfxTable[sfxToRip++]; Audio_PlaySoundGeneral(currentSfx, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); - - { - auto lock = OTRAudio_Lock(); captureThreadState = CT_READY; - } maybeGiveProgressReport(); } void SfxExtractor::finished() { @@ -168,9 +168,10 @@ void SfxExtractor::frameCallback() { } void SfxExtractor::prime() { + int frameLimit = 0;//A couple of sounds don't come to a full stop until another sound is loaded, but should be effectively silent after a couple of seconds. do { AudioMgr_CreateNextAudioBuffer(tempBuffer + 0, SFX_EXTRACTION_ONE_FRAME); - } while (isAllZero(tempBuffer + 0, SFX_EXTRACTION_ONE_FRAME * 2)); + } while (frameLimit ++ < 200 && !isAllSilence(tempBuffer + 0, SFX_EXTRACTION_ONE_FRAME * 2)); captureThreadState = CT_FINISHED; } @@ -187,7 +188,7 @@ void SfxExtractor::captureCallback() { while (samplesLeft > 0) { AudioMgr_CreateNextAudioBuffer(mark, SFX_EXTRACTION_ONE_FRAME); - if (isAllZero(mark, SFX_EXTRACTION_ONE_FRAME * 2)) { + if (isAllSilence(mark, SFX_EXTRACTION_ONE_FRAME * 2)) { if (outputStarted) { break; } else if (waitTime++ < 300) { diff --git a/soh/soh/Enhancements/accessible-actors/SfxExtractor.h b/soh/soh/Enhancements/accessible-actors/SfxExtractor.h index 34d62a043..6fad365ef 100644 --- a/soh/soh/Enhancements/accessible-actors/SfxExtractor.h +++ b/soh/soh/Enhancements/accessible-actors/SfxExtractor.h @@ -1,8 +1,10 @@ #pragma once #include "libultraship/libultraship.h" -#define SFX_EXTRACTION_BUFFER_SIZE 44100 * 15 -#define SFX_EXTRACTION_ONE_FRAME 736 +#define SFX_EXTRACTION_BUFFER_SIZE 32000 * 15 +#define SFX_EXTRACTION_ONE_FRAME 560 +#define SFX_EXTRACTION_SILENCE_THRESHOLD 6//Corresponds to an amplitude of -75dB. + enum CaptureThreadStates { CT_WAITING, // for a sound to start ripping. @@ -29,7 +31,8 @@ class SfxExtractor { // Stores raw audio data for the sfx currently being ripped. int16_t tempBuffer[(SFX_EXTRACTION_BUFFER_SIZE + SFX_EXTRACTION_ONE_FRAME * 3) * 2]; // Check if a buffer contains meaningful audio output. - bool isAllZero(int16_t* buffer, size_t count); + bool isAllSilence(int16_t* buffer, size_t count); + bool isSilentSample(int16_t sample); size_t adjustedStartOfInput(); size_t adjustedEndOfInput(size_t endOfInput); bool renderOutput(size_t endOfInput); diff --git a/soh/soh/Enhancements/accessible-actors/SfxTable.h b/soh/soh/Enhancements/accessible-actors/SfxTable.h index 8f32b861b..a9678d277 100644 --- a/soh/soh/Enhancements/accessible-actors/SfxTable.h +++ b/soh/soh/Enhancements/accessible-actors/SfxTable.h @@ -1092,7 +1092,7 @@ const s16 sfxTable[] = { NA_SE_OC_SECRET_WARP_OUT, NA_SE_OC_SECRET_HOLE_OUT, NA_SE_OC_REVENGE, - NA_SE_OC_HINT_MOVIE, + NA_SE_OC_HINT_MOVIE, NA_SE_OC_HINT_MOVIE2_WHITE, NA_SE_OC_HINT_MOVIE_ZOOMIN, NA_SE_OC_HIBIKI_ISHI, diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 235730ec9..1c4201140 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2628,8 +2628,9 @@ extern "C" void Gfx_RegisterBlendedTexture(const char* name, u8* mask, u8* repla void OTRAudio_SfxCaptureThread() { while (audio.running) { - { - std::unique_lock Lock(audio.mutex); + // This entire body is expected to be atomic; Don't try to narrow the scope of this lock please! + // Todo: remove the thread altogether as we don't actually need or want parallelism here. + std::unique_lock Lock(audio.mutex); while (!audio.processing && audio.running) { audio.cv_to_thread.wait(Lock); } @@ -2637,8 +2638,6 @@ void OTRAudio_SfxCaptureThread() { if (!audio.running) { break; } - } - std::unique_lock Lock(audio.mutex); #if !defined(__SWITCH__) && !defined(__WIIU__) ActorAccessibility_DoSoundExtractionStep(); #endif