Skip to content

Commit

Permalink
Make audio streams handle work as in cleo4 (#230)
Browse files Browse the repository at this point in the history
  • Loading branch information
MiranDMC authored Oct 12, 2024
1 parent d461949 commit de687b2
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 59 deletions.
3 changes: 3 additions & 0 deletions cleo_plugins/Audio/C3DAudioStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
15 changes: 9 additions & 6 deletions cleo_plugins/Audio/CAudioStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down
12 changes: 6 additions & 6 deletions cleo_plugins/Audio/CAudioStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -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!
Expand Down
2 changes: 1 addition & 1 deletion cleo_sdk/CLEO.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
88 changes: 44 additions & 44 deletions examples/Audio_Demo.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// CLEO5 example script
// Sanny Builder 4
// mode: GTA SA(v1.0 - SBL)
// mode: GTA SA (v1.0 - SBL)
{$CLEO .cs}

const Model_Speaker = 2229
const Audio_Path = ".\cleo_tests\Audio\Ding.mp3" // this script's file relative location

wait 1000

int sound_stream, speaker_object
int soundStream, speakerObject
float value, valueCurr


Expand All @@ -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
Expand All @@ -48,23 +48,23 @@ 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
if
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

Expand All @@ -82,27 +82,27 @@ 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
if
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"
Expand All @@ -117,23 +117,23 @@ 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
if
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

Expand All @@ -151,27 +151,27 @@ 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
if
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"
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -270,7 +270,7 @@ while true
end
end

terminate_this_custom_script
terminate_this_script


:START_TEST
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions source/CleoBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit de687b2

Please sign in to comment.