From 3bedd89e1dddda12bbe14040d23cbf7b169ab305 Mon Sep 17 00:00:00 2001 From: jussi Date: Mon, 8 Sep 2025 22:36:40 +0300 Subject: AudioStream management functions. --- src/audio.c | 306 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/core.c | 6 +- src/lua_core.c | 84 ++++++++++++++++ 3 files changed, 395 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/audio.c b/src/audio.c index 47e71ef..d07f806 100644 --- a/src/audio.c +++ b/src/audio.c @@ -386,6 +386,21 @@ int laudioSetSoundPan( lua_State* L ) { return 0; } +/* +> stream = RL.GetSoundStream( Sound sound ) + +Get sound audio stream. Return as lightuserdata + +- Success return AudioStream +*/ +int laudioGetSoundStream( lua_State* L ) { + Sound* sound = uluaGetSound( L, 1 ); + + lua_pushlightuserdata( L, &sound->stream ); + + return 1; +} + /* > RL.WaveFormat( Wave wave, int sampleRate, int sampleSize, int channels ) @@ -716,3 +731,294 @@ int laudioGetMusicTimePlayed( lua_State* L ) { return 1; } + +static float arr[10] = {}; + +/* +> stream = RL.GetMusicStream( Music music ) + +Get music audio stream. Return as lightuserdata + +- Success return AudioStream +*/ +int laudioGetMusicStream( lua_State* L ) { + Music* music = uluaGetMusic( L, 1 ); + + lua_pushlightuserdata( L, &music->stream ); + + return 1; +} + +/* +## Audio - AudioStream management functions +*/ + +/* +> audioStream = RL.LoadAudioStream( int sampleRate, int sampleSize, int channels ) + +Load audio stream (to stream raw audio pcm data) + +- Success return AudioStream +*/ +int laudioLoadAudioStream( lua_State* L ) { + int sampleRate = luaL_checkinteger( L, 1 ); + int sampleSize = luaL_checkinteger( L, 2 ); + int channels = luaL_checkinteger( L, 3 ); + + uluaPushAudioStream( L, LoadAudioStream( sampleRate, sampleSize, channels ) ); + + return 1; +} + +/* +> isValid = RL.IsAudioStreamValid( AudioStream stream ) + +Checks if an audio stream is valid (buffers initialized) + +- Success return bool +*/ +int laudioIsAudioStreamValid( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + + lua_pushboolean( L, IsAudioStreamValid( *stream ) ); + + return 1; +} + +/* +> RL.UnloadAudioStream( AudioStream stream ) + +Unload audio stream and free memory +*/ +int laudioUnloadAudioStream( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + + uluaUnloadAudioStream( stream ); + + return 0; +} + +/* +> RL.UpdateAudioStream( AudioStream stream, Buffer data, int frameCount ) + +Update audio stream buffers with data +*/ +int laudioUpdateAudioStream( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + Buffer* buffer = uluaGetBuffer( L, 2 ); + int frameCount = luaL_checkinteger( L, 3 ); + + UpdateAudioStream( *stream, buffer->data, frameCount ); + + return 0; +} + +/* +> isProcessed = RL.IsAudioStreamProcessed( AudioStream stream ) + +Check if any audio stream buffers requires refill + +- Success return bool +*/ +int laudioIsAudioStreamProcessed( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + + lua_pushboolean( L, IsAudioStreamProcessed( *stream ) ); + + return 1; +} + +/* +> RL.PlayAudioStream( AudioStream stream ) + +Play audio stream +*/ +int laudioPlayAudioStream( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + + PlayAudioStream( *stream ); + + return 0; +} + +/* +> RL.PauseAudioStream( AudioStream stream ) + +Pause audio stream +*/ +int laudioPauseAudioStream( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + + PauseAudioStream( *stream ); + + return 0; +} + +/* +> RL.ResumeAudioStream( AudioStream stream ) + +Resume audio stream +*/ +int laudioResumeAudioStream( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + + ResumeAudioStream( *stream ); + + return 0; +} + +/* +> isPlaying = RL.IsAudioStreamPlaying( AudioStream stream ) + +Check if audio stream is playing + +- Success return bool +*/ +int laudioIsAudioStreamPlaying( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + + lua_pushboolean( L, IsAudioStreamPlaying( *stream ) ); + + return 1; +} + +/* +> RL.StopAudioStream( AudioStream stream ) + +Stop audio stream +*/ +int laudioStopAudioStream( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + + StopAudioStream( *stream ); + + return 0; +} + +/* +> RL.SetAudioStreamVolume( AudioStream stream, float volume ) + +Set volume for audio stream (1.0 is max level) +*/ +int laudioSetAudioStreamVolume( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + float volume = luaL_checknumber( L, 2 ); + + SetAudioStreamVolume( *stream, volume ); + + return 0; +} + +/* +> RL.SetAudioStreamPitch( AudioStream stream, float pitch ) + +Set pitch for audio stream (1.0 is base level) +*/ +int laudioSetAudioStreamPitch( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + float pitch = luaL_checknumber( L, 2 ); + + SetAudioStreamPitch( *stream, pitch ); + + return 0; +} + +/* +> RL.SetAudioStreamPan( AudioStream stream, float pan ) + +Set pan for audio stream (0.5 is centered) +*/ +int laudioSetAudioStreamPan( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + float pan = luaL_checknumber( L, 2 ); + + SetAudioStreamPan( *stream, pan ); + + return 0; +} + +/* +> RL.SetAudioStreamBufferSizeDefault( int size ) + +Default size for new audio streams +*/ +int laudioSetAudioStreamBufferSizeDefault( lua_State* L ) { + int size = luaL_checkinteger( L, 1 ); + + SetAudioStreamBufferSizeDefault( size ); + + return 0; +} + +/* +> RL.SetAudioStreamCallback( AudioStream stream, AudioCallback callback ) + +Audio thread callback to request new data. +AudioCallback should be lightuserdata function pointer +*/ +int laudioSetAudioStreamCallback( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + AudioCallback callback = lua_touserdata( L, 2 ); + + SetAudioStreamCallback( *stream, callback ); + + return 0; +} + +/* +> RL.AttachAudioStreamProcessor( AudioStream stream, AudioCallback processor ) + +Attach audio stream processor to stream, receives the samples as 'float'. +AudioCallback should be lightuserdata function pointer +*/ +int laudioAttachAudioStreamProcessor( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + AudioCallback processor = lua_touserdata( L, 2 ); + + AttachAudioStreamProcessor( *stream, processor ); + + return 0; +} + +/* +> RL.DetachAudioStreamProcessor( AudioStream stream, AudioCallback processor ) + +Detach audio stream processor from stream. +AudioCallback should be lightuserdata function pointer +*/ +int laudioDetachAudioStreamProcessor( lua_State* L ) { + AudioStream* stream = uluaGetAudioStream( L, 1 ); + AudioCallback processor = lua_touserdata( L, 2 ); + + DetachAudioStreamProcessor( *stream, processor ); + + return 0; +} + +/* +> RL.AttachAudioMixedProcessor( AudioCallback processor ) + +Attach audio stream processor to the entire audio pipeline, receives the samples as 'float'. +AudioCallback should be lightuserdata function pointer +*/ +int laudioAttachAudioMixedProcessor( lua_State* L ) { + AudioCallback processor = lua_touserdata( L, 1 ); + + AttachAudioMixedProcessor( processor ); + + return 0; +} + +/* +> RL.DetachAudioMixedProcessor( AudioCallback processor ) + +Detach audio stream processor from the entire audio pipeline. +AudioCallback should be lightuserdata function pointer +*/ +int laudioDetachAudioMixedProcessor( lua_State* L ) { + AudioCallback processor = lua_touserdata( L, 1 ); + + DetachAudioMixedProcessor( processor ); + + return 0; +} diff --git a/src/core.c b/src/core.c index 4cbd551..cd9c9c0 100644 --- a/src/core.c +++ b/src/core.c @@ -3821,7 +3821,11 @@ int lcoreSetBufferData( lua_State* L ) { int len = uluaGetTableLen( L, 3 ); - if ( position < 0 || buffer->size / getBufferElementSize( buffer ) <= ( position + len - 1 ) ) { + // printf( "buffer->size %d len %d position %d element size %d\n", buffer->size, len, position, getBufferElementSize( buffer ) ); + // printf( "Kissa %d %d\n", buffer->size / getBufferElementSize( buffer ), position + len - 1 ); + + // if ( position < 0 || buffer->size / getBufferElementSize( buffer ) <= ( position + len - 1 ) ) { + if ( position < 0 || ( ( buffer->size / getBufferElementSize( buffer ) ) <= ( position + len - 1 ) ) ) { TraceLog( state->logLevelInvalid, "SetBufferData. position %d out of bounds", position ); return 0; } diff --git a/src/lua_core.c b/src/lua_core.c index c4afe80..1a46a5b 100644 --- a/src/lua_core.c +++ b/src/lua_core.c @@ -254,6 +254,25 @@ static void defineMusic() { lua_setfield( L, -2, "__gc" ); } + /* AudioStream. */ +static int gcAudioStream( lua_State* L ) { + if ( state->gcUnload ) { + AudioStream* stream = luaL_checkudata( L, 1, "AudioStream" ); + uluaUnloadAudioStream( stream ); + } + return 0; +} + +static void defineAudioStream() { + lua_State* L = state->luaState; + + luaL_newmetatable( L, "AudioStream" ); + lua_pushvalue( L, -1 ); + lua_setfield( L, -2, "__index" ); + lua_pushcfunction( L, gcAudioStream ); + lua_setfield( L, -2, "__gc" ); +} + /* Light. */ static void defineLight() { lua_State* L = state->luaState; @@ -1341,6 +1360,7 @@ bool luaInit( int argn, const char** argc ) { defineSound(); defineSoundAlias(); defineMusic(); + defineAudioStream(); defineLight(); defineMaterial(); defineMesh(); @@ -2319,6 +2339,27 @@ void luaRegister() { assingGlobalFunction( "GetMusicLooping", laudioGetMusicLooping ); assingGlobalFunction( "GetMusicTimeLength", laudioGetMusicTimeLength ); assingGlobalFunction( "GetMusicTimePlayed", laudioGetMusicTimePlayed ); + assingGlobalFunction( "GetMusicStream", laudioGetMusicStream ); + /* AudioStream management functions. */ + assingGlobalFunction( "LoadAudioStream", laudioLoadAudioStream ); + assingGlobalFunction( "IsAudioStreamValid", laudioIsAudioStreamValid ); + assingGlobalFunction( "UnloadAudioStream", laudioUnloadAudioStream ); + assingGlobalFunction( "UpdateAudioStream", laudioUpdateAudioStream ); + assingGlobalFunction( "IsAudioStreamProcessed", laudioIsAudioStreamProcessed ); + assingGlobalFunction( "PlayAudioStream", laudioPlayAudioStream ); + assingGlobalFunction( "PauseAudioStream", laudioPauseAudioStream ); + assingGlobalFunction( "ResumeAudioStream", laudioResumeAudioStream ); + assingGlobalFunction( "IsAudioStreamPlaying", laudioIsAudioStreamPlaying ); + assingGlobalFunction( "StopAudioStream", laudioStopAudioStream ); + assingGlobalFunction( "SetAudioStreamVolume", laudioSetAudioStreamVolume ); + assingGlobalFunction( "SetAudioStreamPitch", laudioSetAudioStreamPitch ); + assingGlobalFunction( "SetAudioStreamPan", laudioSetAudioStreamPan ); + assingGlobalFunction( "SetAudioStreamBufferSizeDefault", laudioSetAudioStreamBufferSizeDefault ); + assingGlobalFunction( "SetAudioStreamCallback", laudioSetAudioStreamCallback ); + assingGlobalFunction( "AttachAudioStreamProcessor", laudioAttachAudioStreamProcessor ); + assingGlobalFunction( "DetachAudioStreamProcessor", laudioDetachAudioStreamProcessor ); + assingGlobalFunction( "AttachAudioMixedProcessor", laudioAttachAudioMixedProcessor ); + assingGlobalFunction( "DetachAudioMixedProcessor", laudioDetachAudioMixedProcessor ); /* Math. */ /* Utils. */ @@ -3735,6 +3776,36 @@ Music* uluaGetMusic( lua_State* L, int index ) { } } +AudioStream* uluaGetAudioStream( lua_State* L, int index ) { + switch ( lua_type( L, index ) ) { + case LUA_TLIGHTUSERDATA: + return (AudioStream*)lua_touserdata( L, index ); + case LUA_TTABLE: + int t = index, i = 0; + lua_pushnil( L ); + while ( lua_next( L, t ) != 0 ) { + if ( TextIsEqual( "audioStream", lua_tostring( L, -2 ) ) ) { + AudioStream* stream = NULL; + if ( lua_islightuserdata( L, lua_gettop( L ) ) ) { + stream = lua_touserdata( L, lua_gettop( L ) ); + } + else { + stream = luaL_checkudata( L, lua_gettop( L ), "AudioStream" ); + } + lua_pop( L, 2 ); /* Pops also the string. */ + return stream; + } + else { + lua_pop( L, 1 ); + } + i++; + } + /* Don't brake here, we want to get error from default if not found. */ + default: + return luaL_checkudata( L, index, "AudioStream" ); + } +} + Light* uluaGetLight( lua_State* L, int index ) { switch ( lua_type( L, index ) ) { case LUA_TLIGHTUSERDATA: @@ -4238,6 +4309,13 @@ void uluaPushMusic( lua_State* L, Music music ) { luaL_setmetatable( L, "Music" ); } +void uluaPushAudioStream( lua_State* L, AudioStream stream ) { + AudioStream* streamP = lua_newuserdata( L, sizeof( AudioStream ) ); + *streamP = stream; + luaCallLoad( "AudioStream", streamP ); + luaL_setmetatable( L, "AudioStream" ); +} + void uluaPushLight( lua_State* L, Light light ) { Light* lightP = lua_newuserdata( L, sizeof( Light ) ); *lightP = light; @@ -4361,6 +4439,12 @@ void uluaUnloadMusic( Music* music ) { memset( music, 0, sizeof( Music ) ); } +void uluaUnloadAudioStream( AudioStream* stream ) { + luaCallUnload( "AudioStream", stream ); + UnloadAudioStream( *stream ); + memset( stream, 0, sizeof( AudioStream ) ); +} + void uluaUnloadMaterial( Material* material, bool freeAll ) { luaCallUnload( "Material", material ); if ( freeAll ) { -- cgit v1.2.3