Merge branch 'actor-accessibility-experiments' of https://www.github.com/caturria/shipwright into actor-accessibility-experiments

This commit is contained in:
Ryan 2024-01-20 16:18:53 -05:00
commit d236b9df45
12 changed files with 76 additions and 20 deletions

View file

@ -167,6 +167,11 @@ else()
list(FILTER soh__Enhancements EXCLUDE REGEX "soh/Enhancements/speechsynthesizer/(Darwin|SAPI).*") list(FILTER soh__Enhancements EXCLUDE REGEX "soh/Enhancements/speechsynthesizer/(Darwin|SAPI).*")
endif() endif()
# handle accessible audio engine removals
if (CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS")
list(FILTER soh__Enhancements EXCLUDE REGEX "soh/Enhancements/accessible-actors/*")
endif()
source_group("soh\\Enhancements" REGULAR_EXPRESSION "soh/Enhancements/*") source_group("soh\\Enhancements" REGULAR_EXPRESSION "soh/Enhancements/*")
source_group("soh\\Enhancements\\audio" REGULAR_EXPRESSION "soh/Enhancements/audio/*") source_group("soh\\Enhancements\\audio" REGULAR_EXPRESSION "soh/Enhancements/audio/*")
source_group("soh\\Enhancements\\controls" REGULAR_EXPRESSION "soh/Enhancements/controls/*") source_group("soh\\Enhancements\\controls" REGULAR_EXPRESSION "soh/Enhancements/controls/*")

View file

@ -8,8 +8,7 @@
#include <stdio.h> #include <stdio.h>
#include <string> #include <string>
#include <float.h> #include <float.h>
#include "overlays\actors\ovl_Boss_Goma\z_boss_goma.h" #include "overlays/actors/ovl_Boss_Goma/z_boss_goma.h"
//Declarations specific to chests. //Declarations specific to chests.
#include "overlays/actors/ovl_En_Box/z_en_box.h" #include "overlays/actors/ovl_En_Box/z_en_box.h"
extern "C" { extern "C" {

View file

@ -39,7 +39,7 @@ typedef float f32;
typedef int8_t s8; typedef int8_t s8;
typedef uint8_t u8; typedef uint8_t u8;
//Processing for our custom audio positioning. //Processing for our custom audio positioning.
static float lerp(float x, float y, float z) { static float lerp_aae(float x, float y, float z) {
return (1.0 - z) * x + z * y; return (1.0 - z) * x + z * y;
} }
@ -48,9 +48,9 @@ static float lerp(float x, float y, float z) {
return 0; return 0;
float leftover = ma_volume_db_to_linear(AAE_MAX_DB_REDUCTION); float leftover = ma_volume_db_to_linear(AAE_MAX_DB_REDUCTION);
float normDist = fabs(extras->distToPlayer) / extras->maxDistance; float normDist = fabs(extras->distToPlayer) / extras->maxDistance;
float db = lerp(0, AAE_MAX_DB_REDUCTION, normDist); float db = lerp_aae(0, AAE_MAX_DB_REDUCTION, normDist);
float gain = ma_volume_db_to_linear(db); float gain = ma_volume_db_to_linear(db);
gain -= lerp(0, leftover, normDist); gain -= lerp_aae(0, leftover, normDist);
return gain; return gain;
} }
//Borrow the pan calculation from the game itself. Todo: this is technical debt, so copy/ revise it or something at some point. //Borrow the pan calculation from the game itself. Todo: this is technical debt, so copy/ revise it or something at some point.
@ -148,7 +148,7 @@ void AccessibleAudioEngine::doPrepare(SoundAction& action)
//This should not loop more than twice. //This should not loop more than twice.
uint32_t nextChunk = nFrames; uint32_t nextChunk = nFrames;
ma_pcm_rb_acquire_write(&preparedOutput, &nextChunk, (void**)&chunk);//Might reduce nextChunk if there isn't enough buffer space available to accommodate the request. ma_pcm_rb_acquire_write(&preparedOutput, &nextChunk, (void**)&chunk);//Might reduce nextChunk if there isn't enough buffer space available to accommodate the request.
uint64_t framesRead = 0; ma_uint64 framesRead = 0;
ma_engine_read_pcm_frames(&engine, chunk, nextChunk, &framesRead); ma_engine_read_pcm_frames(&engine, chunk, nextChunk, &framesRead);
//Even if we get fewer frames than expected, we should still submit a full buffer of silence. //Even if we get fewer frames than expected, we should still submit a full buffer of silence.
if (framesRead < nextChunk) if (framesRead < nextChunk)
@ -357,7 +357,7 @@ void AccessibleAudioEngine::postHighPrioritySoundAction(SoundAction& action) {
return; return;
slot->extras.cutoff = action.cutoff; slot->extras.cutoff = action.cutoff;
ma_lpf_config config = ma_lpf_config config =
ma_lpf_config_init(ma_format_f32, AAE_CHANNELS, AAE_SAMPLE_RATE, lerp(0.0, AAE_SAMPLE_RATE / 2, action.cutoff), AAE_LPF_ORDER); ma_lpf_config_init(ma_format_f32, AAE_CHANNELS, AAE_SAMPLE_RATE, lerp_aae(0.0, AAE_SAMPLE_RATE / 2, action.cutoff), AAE_LPF_ORDER);
ma_lpf_reinit(&config, &slot->extras.filter); ma_lpf_reinit(&config, &slot->extras.filter);
} }

View file

@ -5,6 +5,7 @@
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <deque> #include <deque>
#include <condition_variable>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <array> #include <array>

View file

@ -187,7 +187,7 @@ int ActorAccessibility_GetRandomStartingFrameCount(int min, int max) {
accessibleActor.sceneIndex = 0; accessibleActor.sceneIndex = 0;
for (int i = 0; i < NUM_MANAGED_SOUND_SLOTS; i++) for (int i = 0; i < NUM_MANAGED_SOUND_SLOTS; i++)
accessibleActor.managedSoundSlots[i] = false; accessibleActor.managedSoundSlots[i] = false;
accessibleActor.aimAssist.framesSinceAimAssist = 0; accessibleActor.aimAssist.framesSinceAimAssist = 32768;
accessibleActor.aimAssist.frequency = 10; accessibleActor.aimAssist.frequency = 10;
accessibleActor.aimAssist.pitch = 1.0; accessibleActor.aimAssist.pitch = 1.0;
@ -399,17 +399,23 @@ int ActorAccessibility_GetRandomStartingFrameCount(int min, int max) {
} }
if (actor->isDrawn == 0 && actor->actor->id != 406 && actor->actor->id != 302) if (actor->isDrawn == 0 && actor->actor->id != 406 && actor->actor->id != 302)
return; return;
if (actor->policy.aimAssist.isProvider && player->stateFlags1 & PLAYER_STATE1_FIRST_PERSON && (player->stateFlags1 & PLAYER_STATE1_BOOMERANG_IN_HAND || player->stateFlags1 & PLAYER_STATE1_ITEM_IN_HAND)) if (actor->policy.aimAssist.isProvider) {
{ if (player->stateFlags1 & PLAYER_STATE1_FIRST_PERSON &&
(player->stateFlags1 & PLAYER_STATE1_BOOMERANG_IN_HAND ||
player->stateFlags1 & PLAYER_STATE1_ITEM_IN_HAND)) {
ActorAccessibility_SetSoundPitch(actor, 9, actor->aimAssist.pitch); ActorAccessibility_SetSoundPitch(actor, 9, actor->aimAssist.pitch);
actor->aimAssist.framesSinceAimAssist++; actor->aimAssist.framesSinceAimAssist++;
ActorAccessibility_ProvideAimAssistForActor(actor); ActorAccessibility_ProvideAimAssistForActor(actor);
//The above will have taken care of setting the appropriate frequency and pitch, so we'll take care of the audio here based on those results. // The above will have taken care of setting the appropriate frequency and pitch, so we'll take care of the
// audio here based on those results.
if (actor->aimAssist.framesSinceAimAssist >= actor->aimAssist.frequency) { if (actor->aimAssist.framesSinceAimAssist >= actor->aimAssist.frequency) {
actor->aimAssist.framesSinceAimAssist = 0; actor->aimAssist.framesSinceAimAssist = 0;
ActorAccessibility_PlaySoundForActor(actor, 9, actor->policy.aimAssist.sfx, false); ActorAccessibility_PlaySoundForActor(actor, 9, actor->policy.aimAssist.sfx, false);
} }
} else
actor->aimAssist.framesSinceAimAssist = 32768;//Make sure there's no delay the next time you draw your bow or whatever.
} }
if (actor->policy.callback != NULL) if (actor->policy.callback != NULL)

View file

@ -74,7 +74,7 @@ struct AccessibleActor {
s16 sceneIndex;//If this actor represents a scene transition, then this will contain the destination scene index. Zero otherwise. s16 sceneIndex;//If this actor represents a scene transition, then this will contain the destination scene index. Zero otherwise.
bool managedSoundSlots[NUM_MANAGED_SOUND_SLOTS];//These have their attenuation and panning parameters updated every frame automatically. bool managedSoundSlots[NUM_MANAGED_SOUND_SLOTS];//These have their attenuation and panning parameters updated every frame automatically.
struct { struct {
s16 framesSinceAimAssist; // Allows rate-based vertical aim assist. Incremented every frame for aim assist u16 framesSinceAimAssist; // Allows rate-based vertical aim assist. Incremented every frame for aim assist
// actors. Manually reset by aim assist provider. // actors. Manually reset by aim assist provider.
f32 pitch; // Used to report whether Link is aiming higher or lower than the actor. f32 pitch; // Used to report whether Link is aiming higher or lower than the actor.
u8 frequency; // How often the sound will be played. Lower frequencies indicate that Link's vertical aim is u8 frequency; // How often the sound will be played. Lower frequencies indicate that Link's vertical aim is

View file

@ -7,6 +7,7 @@
#include "functions.h" #include "functions.h"
#include "soh/OTRGlobals.h" #include "soh/OTRGlobals.h"
#include "SfxTable.h" #include "SfxTable.h"
#include <sstream>
const char* GetLanguageCode(); const char* GetLanguageCode();
extern "C" { extern "C" {
extern Vec3f D_801333D4; extern Vec3f D_801333D4;

View file

@ -2,6 +2,7 @@
#include "z64.h" #include "z64.h"
#include "macros.h" #include "macros.h"
#include "functions.h" #include "functions.h"
#include <cmath>
extern "C" { extern "C" {
s32 Player_PosVsWallLineTest(PlayState* play, Player* p, Vec3f* offset, CollisionPoly** wallPoly, s32* bgId, s32 Player_PosVsWallLineTest(PlayState* play, Player* p, Vec3f* offset, CollisionPoly** wallPoly, s32* bgId,
Vec3f* posResult); Vec3f* posResult);

View file

@ -0,0 +1,16 @@
#include "SpeechLogger.h"
#include <libultraship/libultraship.h>
SpeechLogger::SpeechLogger() {
}
void SpeechLogger::Speak(const char* text, const char* language) {
lusprintf(__FILE__, __LINE__, 2, "Spoken Text (%s): %s", language, text);
}
bool SpeechLogger::DoInit() {
return true;
}
void SpeechLogger::DoUninitialize() {
}

View file

@ -0,0 +1,17 @@
#ifndef SOHSpeechLogger_h
#define SOHSpeechLogger_h
#include "SpeechSynthesizer.h"
class SpeechLogger : public SpeechSynthesizer {
public:
SpeechLogger();
void Speak(const char* text, const char* language);
protected:
bool DoInit(void);
void DoUninitialize(void);
};
#endif

View file

@ -36,3 +36,5 @@ class SpeechSynthesizer {
#elif defined(__APPLE__) #elif defined(__APPLE__)
#include "DarwinSpeechSynthesizer.h" #include "DarwinSpeechSynthesizer.h"
#endif #endif
#include "SpeechLogger.h"

View file

@ -120,12 +120,10 @@ GameInteractorSail* GameInteractorSail::Instance;
#include "soh/resource/importer/BackgroundFactory.h" #include "soh/resource/importer/BackgroundFactory.h"
#include "soh/config/ConfigUpdaters.h" #include "soh/config/ConfigUpdaters.h"
#include "soh/Enhancements/accessible-actors/ActorAccessibility.h" #if !defined(__SWITCH__) && !defined(__WIIU__)
#include "Enhancements//accessible-actors/ActorAccessibility.h" #include "Enhancements/accessible-actors/ActorAccessibility.h"
#endif
void SoH_ProcessDroppedFiles(std::string filePath); void SoH_ProcessDroppedFiles(std::string filePath);
OTRGlobals* OTRGlobals::Instance; OTRGlobals* OTRGlobals::Instance;
SaveManager* SaveManager::Instance; SaveManager* SaveManager::Instance;
CustomMessageManager* CustomMessageManager::Instance; CustomMessageManager* CustomMessageManager::Instance;
@ -506,10 +504,11 @@ void OTRAudio_Thread() {
for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) { for (int i = 0; i < AUDIO_FRAMES_PER_UPDATE; i++) {
AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), AudioMgr_CreateNextAudioBuffer(audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS),
num_audio_samples); num_audio_samples);
#if !defined(__SWITCH__) && !defined(__WIIU__)
// Give accessibility a chance to merge its own audio in. // Give accessibility a chance to merge its own audio in.
ActorAccessibility_MixAccessibleAudioWithGameAudio( ActorAccessibility_MixAccessibleAudioWithGameAudio(
audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), num_audio_samples); audio_buffer + i * (num_audio_samples * NUM_AUDIO_CHANNELS), num_audio_samples);
#endif
} }
AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE)); AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE));
@ -1113,6 +1112,9 @@ extern "C" void InitOTR() {
#elif defined(_WIN32) #elif defined(_WIN32)
SpeechSynthesizer::Instance = new SAPISpeechSynthesizer(); SpeechSynthesizer::Instance = new SAPISpeechSynthesizer();
SpeechSynthesizer::Instance->Init(); SpeechSynthesizer::Instance->Init();
#else
SpeechSynthesizer::Instance = new SpeechLogger();
SpeechSynthesizer::Instance->Init();
#endif #endif
#ifdef ENABLE_REMOTE_CONTROL #ifdef ENABLE_REMOTE_CONTROL
@ -1122,7 +1124,9 @@ extern "C" void InitOTR() {
clearMtx = (uintptr_t)&gMtxClear; clearMtx = (uintptr_t)&gMtxClear;
OTRMessage_Init(); OTRMessage_Init();
#if !defined(__SWITCH__) && !defined(__WIIU__)
ActorAccessibility_Init(); ActorAccessibility_Init();
#endif
OTRAudio_Init(); OTRAudio_Init();
OTRExtScanner(); OTRExtScanner();
VanillaItemTable_Init(); VanillaItemTable_Init();
@ -1185,7 +1189,9 @@ extern "C" void DeinitOTR() {
} }
SDLNet_Quit(); SDLNet_Quit();
#endif #endif
#if !defined(__SWITCH__) && !defined(__WIIU__)
ActorAccessibility_Shutdown(); ActorAccessibility_Shutdown();
#endif
// Destroying gui here because we have shared ptrs to LUS objects which output to SPDLOG which is destroyed before these shared ptrs. // Destroying gui here because we have shared ptrs to LUS objects which output to SPDLOG which is destroyed before these shared ptrs.
SohGui::Destroy(); SohGui::Destroy();
@ -2701,7 +2707,9 @@ void OTRAudio_SfxCaptureThread() {
} }
} }
std::unique_lock<std::mutex> Lock(audio.mutex); std::unique_lock<std::mutex> Lock(audio.mutex);
#if !defined(__SWITCH__) && !defined(__WIIU__)
ActorAccessibility_DoSoundExtractionStep(); ActorAccessibility_DoSoundExtractionStep();
#endif
audio.processing = false; audio.processing = false;
audio.cv_from_thread.notify_one(); audio.cv_from_thread.notify_one();
} }