From de687b2373ddb520c7c998619f5f014d831bc19c Mon Sep 17 00:00:00 2001 From: MiranDMC Date: Sun, 13 Oct 2024 00:05:58 +0200 Subject: [PATCH] Make audio streams handle work as in cleo4 (#230) --- cleo_plugins/Audio/C3DAudioStream.cpp | 3 + cleo_plugins/Audio/CAudioStream.cpp | 15 +++-- cleo_plugins/Audio/CAudioStream.h | 12 ++-- cleo_sdk/CLEO.h | 2 +- examples/Audio_Demo.txt | 88 +++++++++++++-------------- source/CleoBase.cpp | 4 +- 6 files changed, 65 insertions(+), 59 deletions(-) diff --git a/cleo_plugins/Audio/C3DAudioStream.cpp b/cleo_plugins/Audio/C3DAudioStream.cpp index 88861175..258ba472 100644 --- a/cleo_plugins/Audio/C3DAudioStream.cpp +++ b/cleo_plugins/Audio/C3DAudioStream.cpp @@ -6,6 +6,9 @@ using namespace CLEO; C3DAudioStream::C3DAudioStream(const char* filepath) : CAudioStream() { + // see https://github.com/cleolibrary/CLEO5/pull/230 + static_assert(offsetof(C3DAudioStream, streamInternal) == 4 && alignof(C3DAudioStream) == 4, "C3DAudioStream compatibility with CLEO4 broken!"); + if (isNetworkSource(filepath) && !CSoundSystem::allowNetworkSources) { TRACE("Loading of 3d-audiostream '%s' failed. Support of network sources was disabled in SA.Audio.ini", filepath); diff --git a/cleo_plugins/Audio/CAudioStream.cpp b/cleo_plugins/Audio/CAudioStream.cpp index 03dae03b..3be270d2 100644 --- a/cleo_plugins/Audio/CAudioStream.cpp +++ b/cleo_plugins/Audio/CAudioStream.cpp @@ -6,6 +6,9 @@ using namespace CLEO; CAudioStream::CAudioStream(const char* filepath) { + // see https://github.com/cleolibrary/CLEO5/pull/230 + static_assert(offsetof(CAudioStream, streamInternal) == 4 && alignof(CAudioStream) == 4, "CAudioStream compatibility with CLEO4 broken!"); + if (isNetworkSource(filepath) && !CSoundSystem::allowNetworkSources) { TRACE("Loading of audiostream '%s' failed. Support of network sources was disabled in SA.Audio.ini", filepath); @@ -111,7 +114,7 @@ void CAudioStream::SetVolume(float value, float transitionTime) if (transitionTime <= 0.0) volume = value; // instant else - volumeTransitionStep = (volumeTarget - volume) / (1000.0 * transitionTime); + volumeTransitionStep = (volumeTarget - volume) / (1000.0f * transitionTime); } float CAudioStream::GetVolume() const @@ -129,7 +132,7 @@ void CAudioStream::SetSpeed(float value, float transitionTime) if (transitionTime <= 0.0) speed = value; // instant else - speedTransitionStep = (speedTarget - speed) / (1000.0 * transitionTime); + speedTransitionStep = (speedTarget - speed) / (1000.0f * transitionTime); } float CAudioStream::GetSpeed() const @@ -161,11 +164,11 @@ void CAudioStream::UpdateVolume() if (volume != volumeTarget) { auto timeDelta = CTimer::m_snTimeInMillisecondsNonClipped - CTimer::m_snPreviousTimeInMillisecondsNonClipped; - volume += volumeTransitionStep * (double)timeDelta; // animate the transition + volume += volumeTransitionStep * (float)timeDelta; // animate the transition // check progress auto remaining = volumeTarget - volume; - remaining *= (volumeTransitionStep > 0.0) ? 1.0 : -1.0; + remaining *= (volumeTransitionStep > 0.0f) ? 1.0f : -1.0f; if (remaining < 0.0) // overshoot { volume = volumeTarget; @@ -188,11 +191,11 @@ void CAudioStream::UpdateSpeed() if (speed != speedTarget) { auto timeDelta = CTimer::m_snTimeInMillisecondsNonClipped - CTimer::m_snPreviousTimeInMillisecondsNonClipped; - speed += speedTransitionStep * (double)timeDelta; // animate the transition + speed += speedTransitionStep * (float)timeDelta; // animate the transition // check progress auto remaining = speedTarget - speed; - remaining *= (speedTransitionStep > 0.0) ? 1.0 : -1.0; + remaining *= (speedTransitionStep > 0.0f) ? 1.0f : -1.0f; if (remaining < 0.0) // overshoot { speed = speedTarget; // done diff --git a/cleo_plugins/Audio/CAudioStream.h b/cleo_plugins/Audio/CAudioStream.h index fdfa2b60..514084ff 100644 --- a/cleo_plugins/Audio/CAudioStream.h +++ b/cleo_plugins/Audio/CAudioStream.h @@ -58,14 +58,14 @@ namespace CLEO eStreamType type = eStreamType::SoundEffect; bool ok = false; float rate = 44100.0f; // file's sampling rate - double speed = 1.0f; - double volume = 1.0f; + float speed = 1.0f; + float volume = 1.0f; // transitions - double volumeTarget = 1.0f; - double volumeTransitionStep = 1.0f; - double speedTarget = 1.0f; - double speedTransitionStep = 1.0f; + float volumeTarget = 1.0f; + float volumeTransitionStep = 1.0f; + float speedTarget = 1.0f; + float speedTransitionStep = 1.0f; CAudioStream() = default; CAudioStream(const CAudioStream&) = delete; // no copying! diff --git a/cleo_sdk/CLEO.h b/cleo_sdk/CLEO.h index 1a1d3c83..a73a328f 100644 --- a/cleo_sdk/CLEO.h +++ b/cleo_sdk/CLEO.h @@ -530,7 +530,7 @@ void WINAPI CLEO_RemoveScriptDeleteDelegate(FuncScriptDeleteDelegateT func); DWORD WINAPI CLEO_GetScriptTextureById(CRunningScript* thread, int id); // ret RwTexture * -DWORD WINAPI CLEO_GetInternalAudioStream(CRunningScript* thread, DWORD stream); // arg CAudioStream * +DWORD WINAPI CLEO_GetInternalAudioStream(CRunningScript* unused, DWORD audioStreamPtr); // CAudioStream* struct StringList { DWORD count; char** strings; }; void WINAPI CLEO_StringListFree(StringList list); // releases resources used by StringList container diff --git a/examples/Audio_Demo.txt b/examples/Audio_Demo.txt index b4a564dd..3aeaeb7e 100644 --- a/examples/Audio_Demo.txt +++ b/examples/Audio_Demo.txt @@ -1,6 +1,6 @@ // CLEO5 example script // Sanny Builder 4 -// mode: GTA SA(v1.0 - SBL) +// mode: GTA SA (v1.0 - SBL) {$CLEO .cs} const Model_Speaker = 2229 @@ -8,7 +8,7 @@ const Audio_Path = ".\cleo_tests\Audio\Ding.mp3" // this script's file relative wait 1000 -int sound_stream, speaker_object +int soundStream, speakerObject float value, valueCurr @@ -23,17 +23,17 @@ while true START_TEST() if - not load_3d_audio_stream Audio_Path {store_to} sound_stream + not load_3d_audio_stream Audio_Path {store_to} soundStream then print_formatted_now "~r~Failed to load audio file!" {time} 10000 END_TEST() continue end - set_play_3d_audio_stream_at_object sound_stream {object} speaker_object - set_audio_stream_state sound_stream AudioStreamAction.Play + set_play_3d_audio_stream_at_object soundStream {object} speakerObject + set_audio_stream_state soundStream AudioStreamAction.Play - while is_audio_stream_playing sound_stream - valueCurr = get_audio_stream_progress sound_stream + while is_audio_stream_playing soundStream + valueCurr = get_audio_stream_progress soundStream print_formatted_now "DEMO 1: Get progress: %.2f" {time} 0 {args} valueCurr wait 0 end @@ -48,15 +48,15 @@ while true START_TEST() if - not load_3d_audio_stream Audio_Path {store_to} sound_stream + not load_3d_audio_stream Audio_Path {store_to} soundStream then print_formatted_now "~r~Failed to load audio file!" {time} 10000 END_TEST() continue end - set_play_3d_audio_stream_at_object sound_stream {object} speaker_object - set_audio_stream_looped sound_stream true - set_audio_stream_state sound_stream AudioStreamAction.Play + set_play_3d_audio_stream_at_object soundStream {object} speakerObject + set_audio_stream_looped soundStream true + set_audio_stream_state soundStream AudioStreamAction.Play TIMERA = 1000 repeat @@ -64,7 +64,7 @@ while true TIMERA >= 1000 then value = generate_random_float_in_range 0.0 2.0 - set_audio_stream_volume sound_stream value + set_audio_stream_volume soundStream value TIMERA = 0 end @@ -82,15 +82,15 @@ while true START_TEST() if - not load_3d_audio_stream Audio_Path {store_to} sound_stream + not load_3d_audio_stream Audio_Path {store_to} soundStream then print_formatted_now "~r~Failed to load audio file!" {time} 10000 END_TEST() continue end - set_play_3d_audio_stream_at_object sound_stream {object} speaker_object - set_audio_stream_looped sound_stream true - set_audio_stream_state sound_stream AudioStreamAction.Play + set_play_3d_audio_stream_at_object soundStream {object} speakerObject + set_audio_stream_looped soundStream true + set_audio_stream_state soundStream AudioStreamAction.Play TIMERA = 2000 repeat @@ -98,11 +98,11 @@ while true TIMERA >= 2000 then value = generate_random_float_in_range 0.0 2.0 - set_audio_stream_volume_with_transition sound_stream {volume} value {timeMs} 1000 + set_audio_stream_volume_with_transition soundStream {volume} value {timeMs} 1000 TIMERA = 0 end - valueCurr = get_audio_stream_volume sound_stream + valueCurr = get_audio_stream_volume soundStream print_formatted_now "DEMO 3: Set volume: %.2f, Transition: 1.0s~n~Current volume: %.2f~n~Press 3 to stop" {time} 0 {args} value valueCurr wait 0 until test_cheat "3" @@ -117,15 +117,15 @@ while true START_TEST() if - not load_3d_audio_stream Audio_Path {store_to} sound_stream + not load_3d_audio_stream Audio_Path {store_to} soundStream then print_formatted_now "~r~Failed to load audio file!" {time} 10000 END_TEST() continue end - set_play_3d_audio_stream_at_object sound_stream {object} speaker_object - set_audio_stream_looped sound_stream true - set_audio_stream_state sound_stream AudioStreamAction.Play + set_play_3d_audio_stream_at_object soundStream {object} speakerObject + set_audio_stream_looped soundStream true + set_audio_stream_state soundStream AudioStreamAction.Play TIMERA = 1000 repeat @@ -133,7 +133,7 @@ while true TIMERA >= 1000 then value = generate_random_float_in_range 0.0 2.0 - set_audio_stream_speed sound_stream value + set_audio_stream_speed soundStream value TIMERA = 0 end @@ -151,15 +151,15 @@ while true START_TEST() if - not load_3d_audio_stream Audio_Path {store_to} sound_stream + not load_3d_audio_stream Audio_Path {store_to} soundStream then print_formatted_now "~r~Failed to load audio file!" {time} 10000 END_TEST() continue end - set_play_3d_audio_stream_at_object sound_stream {object} speaker_object - set_audio_stream_looped sound_stream true - set_audio_stream_state sound_stream AudioStreamAction.Play + set_play_3d_audio_stream_at_object soundStream {object} speakerObject + set_audio_stream_looped soundStream true + set_audio_stream_state soundStream AudioStreamAction.Play TIMERA = 2000 repeat @@ -167,11 +167,11 @@ while true TIMERA >= 2000 then value = generate_random_float_in_range 0.0 2.0 - set_audio_stream_speed_with_transition sound_stream {volume} value {timeMs} 1000 + set_audio_stream_speed_with_transition soundStream {volume} value {timeMs} 1000 TIMERA = 0 end - valueCurr = get_audio_stream_speed sound_stream + valueCurr = get_audio_stream_speed soundStream print_formatted_now "DEMO 5: Set speed: %.2f, Transition: 1.0s~n~Current speed: %.2f~n~Press 5 to stop" {time} 0 {args} value valueCurr wait 0 until test_cheat "5" @@ -186,16 +186,16 @@ while true START_TEST() if - not load_3d_audio_stream Audio_Path {store_to} sound_stream + not load_3d_audio_stream Audio_Path {store_to} soundStream then print_formatted_now "~r~Failed to load audio file!" {time} 10000 END_TEST() continue end - set_play_3d_audio_stream_at_object sound_stream {object} speaker_object - set_audio_stream_looped sound_stream true - set_audio_stream_volume sound_stream {volume} 4.0 - set_audio_stream_state sound_stream AudioStreamAction.Play + set_play_3d_audio_stream_at_object soundStream {object} speakerObject + set_audio_stream_looped soundStream true + set_audio_stream_volume soundStream {volume} 4.0 + set_audio_stream_state soundStream AudioStreamAction.Play wait 1000 int direction = 0 @@ -229,15 +229,15 @@ while true START_TEST() if - not load_3d_audio_stream Audio_Path {store_to} sound_stream + not load_3d_audio_stream Audio_Path {store_to} soundStream then print_formatted_now "~r~Failed to load audio file!" {time} 10000 END_TEST() continue end - set_play_3d_audio_stream_at_object sound_stream {object} speaker_object - set_audio_stream_looped sound_stream true - set_audio_stream_state sound_stream AudioStreamAction.Play + set_play_3d_audio_stream_at_object soundStream {object} speakerObject + set_audio_stream_looped soundStream true + set_audio_stream_state soundStream AudioStreamAction.Play // walk set_player_control 0 {control} false @@ -247,7 +247,7 @@ while true extend_route {xyz} 231.0 2525.0 15.5 extend_route {xyz} 230.0 2526.0 15.5 task_follow_point_route $scplayer {walk_speed} 6 {flag} 3 - task_look_at_object $scplayer {object} speaker_object {time} -1 + task_look_at_object $scplayer {object} speakerObject {time} -1 TIMERA = 2000 repeat @@ -270,7 +270,7 @@ while true end end -terminate_this_custom_script +terminate_this_script :START_TEST @@ -293,16 +293,16 @@ terminate_this_custom_script // create speaker object (visual only) request_model {modelId} Model_Speaker load_all_models_now - speaker_object = create_object {modelId} Model_Speaker {xyz} 230.25 2525.0 16.0 + speakerObject = create_object {modelId} Model_Speaker {xyz} 230.25 2525.0 16.0 mark_model_as_no_longer_needed {modelId} Model_Speaker - set_object_collision speaker_object {state} false + set_object_collision speakerObject {state} false point_camera_at_point {xyz} 230.0 2525.0 16.5 {switchStyle} SwitchType.Interpolation return :END_TEST - remove_audio_stream sound_stream - delete_object speaker_object + remove_audio_stream soundStream + delete_object speakerObject camera_reset_new_scriptables restore_camera display_hud true diff --git a/source/CleoBase.cpp b/source/CleoBase.cpp index a532b2af..fefc469a 100644 --- a/source/CleoBase.cpp +++ b/source/CleoBase.cpp @@ -252,9 +252,9 @@ namespace CLEO GetInstance().RemoveCallback(id, func); } - DWORD WINAPI CLEO_GetInternalAudioStream(CLEO::CRunningScript* thread, DWORD stream) // arg CAudioStream * + DWORD WINAPI CLEO_GetInternalAudioStream(CLEO::CRunningScript* unused, DWORD audioStreamPtr) { - return stream; // CAudioStream::streamInternal offset is 0 + return *(DWORD*)(audioStreamPtr + 0x4); // CAudioStream->streamInternal } void WINAPI CLEO_ResolvePath(CLEO::CRunningScript* thread, char* inOutPath, DWORD pathMaxLen)