AudioStream management functions.

This commit is contained in:
jussi
2025-09-08 22:36:40 +03:00
parent de672a85d2
commit 3bedd89e1d
15 changed files with 901 additions and 5 deletions

147
API.md
View File

@@ -9401,6 +9401,14 @@ Set pan for a sound (0.5 is center)
--- ---
> stream = RL.GetSoundStream( Sound sound )
Get sound audio stream. Return as lightuserdata
- Success return AudioStream
---
> RL.WaveFormat( Wave wave, int sampleRate, int sampleSize, int channels ) > RL.WaveFormat( Wave wave, int sampleRate, int sampleSize, int channels )
Convert wave data to desired format Convert wave data to desired format
@@ -9555,6 +9563,145 @@ Get current music time played (in seconds)
--- ---
> stream = RL.GetMusicStream( Music music )
Get music audio stream. Return as lightuserdata
- Success return AudioStream
---
## 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
---
> isValid = RL.IsAudioStreamValid( AudioStream stream )
Checks if an audio stream is valid (buffers initialized)
- Success return bool
---
> RL.UnloadAudioStream( AudioStream stream )
Unload audio stream and free memory
---
> RL.UpdateAudioStream( AudioStream stream, Buffer data, int frameCount )
Update audio stream buffers with data
---
> isProcessed = RL.IsAudioStreamProcessed( AudioStream stream )
Check if any audio stream buffers requires refill
- Success return bool
---
> RL.PlayAudioStream( AudioStream stream )
Play audio stream
---
> RL.PauseAudioStream( AudioStream stream )
Pause audio stream
---
> RL.ResumeAudioStream( AudioStream stream )
Resume audio stream
---
> isPlaying = RL.IsAudioStreamPlaying( AudioStream stream )
Check if audio stream is playing
- Success return bool
---
> RL.StopAudioStream( AudioStream stream )
Stop audio stream
---
> RL.SetAudioStreamVolume( AudioStream stream, float volume )
Set volume for audio stream (1.0 is max level)
---
> RL.SetAudioStreamPitch( AudioStream stream, float pitch )
Set pitch for audio stream (1.0 is base level)
---
> RL.SetAudioStreamPan( AudioStream stream, float pan )
Set pan for audio stream (0.5 is centered)
---
> RL.SetAudioStreamBufferSizeDefault( int size )
Default size for new audio streams
---
> RL.SetAudioStreamCallback( AudioStream stream, AudioCallback callback )
Audio thread callback to request new data.
AudioCallback should be lightuserdata function pointer
---
> RL.AttachAudioStreamProcessor( AudioStream stream, AudioCallback processor )
Attach audio stream processor to stream, receives the samples as 'float'.
AudioCallback should be lightuserdata function pointer
---
> RL.DetachAudioStreamProcessor( AudioStream stream, AudioCallback processor )
Detach audio stream processor from stream.
AudioCallback should be lightuserdata function pointer
---
> RL.AttachAudioMixedProcessor( AudioCallback processor )
Attach audio stream processor to the entire audio pipeline, receives the samples as 'float'.
AudioCallback should be lightuserdata function pointer
---
> RL.DetachAudioMixedProcessor( AudioCallback processor )
Detach audio stream processor from the entire audio pipeline.
AudioCallback should be lightuserdata function pointer
---
## Math - Utils ## Math - Utils
--- ---

View File

@@ -26,8 +26,6 @@ List of some MISSING features that are planned to be included. For specific func
* Core * Core
* VR stereo config functions for VR simulator * VR stereo config functions for VR simulator
* Audio
* AudioStream management functions
## Roadmap ## Roadmap

View File

@@ -5823,6 +5823,12 @@ function RL.SetSoundPitch( sound, pitch ) end
---@return any RL.SetSoundPan ---@return any RL.SetSoundPan
function RL.SetSoundPan( sound, pan ) end function RL.SetSoundPan( sound, pan ) end
---Get sound audio stream. Return as lightuserdata
---- Success return AudioStream
---@param sound any
---@return any stream
function RL.GetSoundStream( sound ) end
---Convert wave data to desired format ---Convert wave data to desired format
---@param wave any ---@param wave any
---@param sampleRate integer ---@param sampleRate integer
@@ -5955,6 +5961,128 @@ function RL.GetMusicTimeLength( music ) end
---@return any timePlayed ---@return any timePlayed
function RL.GetMusicTimePlayed( music ) end function RL.GetMusicTimePlayed( music ) end
---Get music audio stream. Return as lightuserdata
---- Success return AudioStream
---@param music any
---@return any stream
function RL.GetMusicStream( music ) end
-- Audio - AudioStream management functions
---Load audio stream (to stream raw audio pcm data)
---- Success return AudioStream
---@param sampleRate integer
---@param sampleSize integer
---@param channels integer
---@return any audioStream
function RL.LoadAudioStream( sampleRate, sampleSize, channels ) end
---Checks if an audio stream is valid (buffers initialized)
---- Success return bool
---@param stream any
---@return any isValid
function RL.IsAudioStreamValid( stream ) end
---Unload audio stream and free memory
---@param stream any
---@return any RL.UnloadAudioStream
function RL.UnloadAudioStream( stream ) end
---Update audio stream buffers with data
---@param stream any
---@param data any
---@param frameCount integer
---@return any RL.UpdateAudioStream
function RL.UpdateAudioStream( stream, data, frameCount ) end
---Check if any audio stream buffers requires refill
---- Success return bool
---@param stream any
---@return any isProcessed
function RL.IsAudioStreamProcessed( stream ) end
---Play audio stream
---@param stream any
---@return any RL.PlayAudioStream
function RL.PlayAudioStream( stream ) end
---Pause audio stream
---@param stream any
---@return any RL.PauseAudioStream
function RL.PauseAudioStream( stream ) end
---Resume audio stream
---@param stream any
---@return any RL.ResumeAudioStream
function RL.ResumeAudioStream( stream ) end
---Check if audio stream is playing
---- Success return bool
---@param stream any
---@return any isPlaying
function RL.IsAudioStreamPlaying( stream ) end
---Stop audio stream
---@param stream any
---@return any RL.StopAudioStream
function RL.StopAudioStream( stream ) end
---Set volume for audio stream (1.0 is max level)
---@param stream any
---@param volume number
---@return any RL.SetAudioStreamVolume
function RL.SetAudioStreamVolume( stream, volume ) end
---Set pitch for audio stream (1.0 is base level)
---@param stream any
---@param pitch number
---@return any RL.SetAudioStreamPitch
function RL.SetAudioStreamPitch( stream, pitch ) end
---Set pan for audio stream (0.5 is centered)
---@param stream any
---@param pan number
---@return any RL.SetAudioStreamPan
function RL.SetAudioStreamPan( stream, pan ) end
---Default size for new audio streams
---@param size integer
---@return any RL.SetAudioStreamBufferSizeDefault
function RL.SetAudioStreamBufferSizeDefault( size ) end
---Audio thread callback to request new data.
---AudioCallback should be lightuserdata function pointer
---@param stream any
---@param callback any
---@return any RL.SetAudioStreamCallback
function RL.SetAudioStreamCallback( stream, callback ) end
---Attach audio stream processor to stream, receives the samples as 'float'.
---AudioCallback should be lightuserdata function pointer
---@param stream any
---@param processor any
---@return any RL.AttachAudioStreamProcessor
function RL.AttachAudioStreamProcessor( stream, processor ) end
---Detach audio stream processor from stream.
---AudioCallback should be lightuserdata function pointer
---@param stream any
---@param processor any
---@return any RL.DetachAudioStreamProcessor
function RL.DetachAudioStreamProcessor( stream, processor ) end
---Attach audio stream processor to the entire audio pipeline, receives the samples as 'float'.
---AudioCallback should be lightuserdata function pointer
---@param processor any
---@return any RL.AttachAudioMixedProcessor
function RL.AttachAudioMixedProcessor( processor ) end
---Detach audio stream processor from the entire audio pipeline.
---AudioCallback should be lightuserdata function pointer
---@param processor any
---@return any RL.DetachAudioMixedProcessor
function RL.DetachAudioMixedProcessor( processor ) end
-- Math - Utils -- Math - Utils
---Round float value ---Round float value

View File

@@ -56,6 +56,9 @@ DETAILED CHANGES:
- ADDED: MeasureTextBoxed. - ADDED: MeasureTextBoxed.
- CHANGE: DrawTextBoxedEx to DrawTextBoxed. - CHANGE: DrawTextBoxedEx to DrawTextBoxed.
- CHANGE: DrawMeshInstanced takes transforms as Buffer. Much better performance. - CHANGE: DrawMeshInstanced takes transforms as Buffer. Much better performance.
- ADDED: AudioStream management functions.
- ADDED: GetSoundStream and GetMusicStream.
- ADDED: Audio stream effects example.
------------------------------------------------------------------------ ------------------------------------------------------------------------
Release: ReiLua version 0.8.0 Using Raylib 5.0 and Forked Raygui 4.0 Release: ReiLua version 0.8.0 Using Raylib 5.0 and Forked Raygui 4.0

View File

@@ -11,8 +11,6 @@ Backlog {
* Text input not working on gui. Could this be Raylib issue? * Text input not working on gui. Could this be Raylib issue?
* Haptic functions. * Haptic functions.
* SDL3 GPU? * SDL3 GPU?
* Audio
* AudioStream.
* Models * Models
* Material mapType range checks. * Material mapType range checks.
* Mesh bone weight management? * Mesh bone weight management?
@@ -27,6 +25,7 @@ Bugs {
} }
Notes { Notes {
* WARNING: BREAKING CHANGE: LoadFontData() has been redesigned! https://github.com/raysan5/raylib/commit/29ce5d8aa9d261eba395e24437e08c6bd744616e
} }
Needs Testing { Needs Testing {

View File

@@ -0,0 +1,100 @@
-- Based on raylib audio_stream_effects example
package.path = package.path..";"..RL.GetBasePath().."../resources/lib/?.lua"
package.cpath = package.cpath..";"..RL.GetBasePath().."../resources/clib/?.so"
Vector2 = require( "vector2" )
Rect = require( "rectangle" )
-- NOTE! You have to compile the C lib containing the effects in resources/clib/audioProcess.c
-- Implementing audio processors in Lua would probably be too slow.
AudioProcess = require( "audioProcess" )
local music = nil
local rect = Rect:new()
local rect2 = Rect:new()
local effectLPF = nil
local effectDelay = nil
local enableEffectLPF = false
local enableEffectDelay = false
function RL.init()
RL.SetWindowTitle( "Audio stream effects" )
RL.SetWindowState( RL.FLAG_VSYNC_HINT )
RL.InitAudioDevice()
music = RL.LoadMusicStream( RL.GetBasePath().."../resources/music/Juhani Junkala [Retro Game Music Pack] Title Screen.ogg" )
RL.PlayMusicStream( music )
AudioProcess.init()
effectLPF = AudioProcess.AudioProcessEffectLPF()
effectDelay = AudioProcess.AudioProcessEffectDelay()
local winSize = Vector2:newT( RL.GetScreenSize() )
local barWidth = 256
rect:set(
winSize.x / 2 - barWidth / 2,
winSize.y / 2 - 5,
barWidth,
10
)
rect2:setR( rect )
end
function RL.update( delta )
RL.UpdateMusicStream( music )
-- Add/Remove effect: lowpass filter
if RL.IsKeyPressed( RL.KEY_F ) then
local stream = RL.GetMusicStream( music )
enableEffectLPF = not enableEffectLPF
if enableEffectLPF then
RL.AttachAudioStreamProcessor( stream, effectLPF )
-- RL.AttachAudioMixedProcessor( effectLPF )
else
RL.DetachAudioStreamProcessor( stream, effectLPF )
-- RL.DetachAudioMixedProcessor( effectLPF )
end
end
-- Add/Remove effect: delay
if RL.IsKeyPressed( RL.KEY_D ) then
local stream = RL.GetMusicStream( music )
enableEffectDelay = not enableEffectDelay
if enableEffectDelay then
RL.AttachAudioStreamProcessor( stream, effectDelay )
-- RL.AttachAudioMixedProcessor( effectDelay )
else
RL.DetachAudioStreamProcessor( stream, effectDelay )
-- RL.DetachAudioMixedProcessor( effectDelay )
end
end
end
function RL.draw()
local musicLen = RL.GetMusicTimeLength( music )
local musicPos = RL.GetMusicTimePlayed( music )
RL.ClearBackground( RL.RAYWHITE )
RL.DrawText(
"PRESS F TO TOGGLE LPF EFFECT "..( enableEffectLPF and "ON" or "OFF" ),
Vector2:temp( rect.x - 80, rect.y - 80 ), 20, RL.GRAY
)
RL.DrawText(
"PRESS D TO TOGGLE DELAY EFFECT "..( enableEffectDelay and "ON" or "OFF" ),
Vector2:temp( rect.x - 90, rect.y - 40 ), 20, RL.GRAY
)
RL.DrawRectangleLines( rect + Rect:temp( 0, -1, 1, 1 ), RL.BLACK )
rect2.width = musicPos / musicLen * rect.width
RL.DrawRectangle( rect2, RL.RED )
end
function RL.exit()
AudioProcess.free()
end

1
examples/resources/clib/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.so

View File

@@ -0,0 +1,100 @@
/* Based on raylib audio_stream_effects example */
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* gcc audioProcess.c -shared -o audioProcess.so -fPIC -llua */
// Audio effect: lowpass filter
void AudioProcessEffectLPF(void *buffer, unsigned int frames)
{
static float low[2] = { 0.0f, 0.0f };
static const float cutoff = 70.0f / 44100.0f; // 70 Hz lowpass filter
const float k = cutoff / (cutoff + 0.1591549431f); // RC filter formula
// Converts the buffer data before using it
float *bufferData = (float *)buffer;
for (unsigned int i = 0; i < frames*2; i += 2)
{
const float l = bufferData[i];
const float r = bufferData[i + 1];
low[0] += k * (l - low[0]);
low[1] += k * (r - low[1]);
bufferData[i] = low[0];
bufferData[i + 1] = low[1];
}
}
static float *delayBuffer = NULL;
static unsigned int delayBufferSize = 0;
static unsigned int delayReadIndex = 2;
static unsigned int delayWriteIndex = 0;
// Audio effect: delay
static void AudioProcessEffectDelay(void *buffer, unsigned int frames)
{
for (unsigned int i = 0; i < frames*2; i += 2)
{
float leftDelay = delayBuffer[delayReadIndex++]; // ERROR: Reading buffer -> WHY??? Maybe thread related???
float rightDelay = delayBuffer[delayReadIndex++];
if (delayReadIndex == delayBufferSize) delayReadIndex = 0;
((float *)buffer)[i] = 0.5f*((float *)buffer)[i] + 0.5f*leftDelay;
((float *)buffer)[i + 1] = 0.5f*((float *)buffer)[i + 1] + 0.5f*rightDelay;
delayBuffer[delayWriteIndex++] = ((float *)buffer)[i];
delayBuffer[delayWriteIndex++] = ((float *)buffer)[i + 1];
if (delayWriteIndex == delayBufferSize) delayWriteIndex = 0;
}
}
/* API. */
static int apInit( lua_State* L ) {
// Allocate buffer for the delay effect
delayBufferSize = 48000*2; // 1 second delay (device sampleRate*channels)
delayBuffer = (float *)calloc(delayBufferSize, sizeof(float));
return 0;
}
static int getAudioProcessEffectLPF( lua_State* L ) {
lua_pushlightuserdata( L, AudioProcessEffectLPF );
return 1;
}
static int getAudioProcessEffectDelay( lua_State* L ) {
lua_pushlightuserdata( L, AudioProcessEffectDelay );
return 1;
}
static int apFree( lua_State* L ) {
free(delayBuffer); // Free delay buffer
return 0;
}
static const luaL_Reg audioProcess[] = {
{ "init", apInit },
{ "AudioProcessEffectLPF", getAudioProcessEffectLPF },
{ "AudioProcessEffectDelay", getAudioProcessEffectDelay },
{ "free", apFree },
{ NULL, NULL } // sentinel.
};
int luaopen_audioProcess(lua_State *L) {
#if LUA_VERSION_NUM <= 501
luaL_openlib( L, "audioProcess", audioProcess, 0 );
#else
luaL_newlib( L, audioProcess );
#endif
return 1;
}

View File

@@ -0,0 +1,2 @@
Resource Author Licence Source Edits
Juhani Junkala [Retro Game Music Pack] Title Screen Juhani Junkala CC0 https://opengameart.org/content/5-chiptunes-action

View File

@@ -52,3 +52,24 @@ int laudioSetMusicLooping( lua_State* L );
int laudioGetMusicLooping( lua_State* L ); int laudioGetMusicLooping( lua_State* L );
int laudioGetMusicTimeLength( lua_State* L ); int laudioGetMusicTimeLength( lua_State* L );
int laudioGetMusicTimePlayed( lua_State* L ); int laudioGetMusicTimePlayed( lua_State* L );
int laudioGetMusicStream( lua_State* L );
/* Audio - AudioStream management functions. */
int laudioLoadAudioStream( lua_State* L );
int laudioIsAudioStreamValid( lua_State* L );
int laudioUnloadAudioStream( lua_State* L );
int laudioUpdateAudioStream( lua_State* L );
int laudioIsAudioStreamProcessed( lua_State* L );
int laudioPlayAudioStream( lua_State* L );
int laudioPauseAudioStream( lua_State* L );
int laudioResumeAudioStream( lua_State* L );
int laudioIsAudioStreamPlaying( lua_State* L );
int laudioStopAudioStream( lua_State* L );
int laudioSetAudioStreamVolume( lua_State* L );
int laudioSetAudioStreamPitch( lua_State* L );
int laudioSetAudioStreamPan( lua_State* L );
int laudioSetAudioStreamBufferSizeDefault( lua_State* L );
int laudioSetAudioStreamCallback( lua_State* L );
int laudioAttachAudioStreamProcessor( lua_State* L );
int laudioDetachAudioStreamProcessor( lua_State* L );
int laudioAttachAudioMixedProcessor( lua_State* L );
int laudioDetachAudioMixedProcessor( lua_State* L );

View File

@@ -87,6 +87,7 @@ REILUAPI GlyphInfo* uluaGetGlyphInfo( lua_State* L, int index );
REILUAPI Wave* uluaGetWave( lua_State* L, int index ); REILUAPI Wave* uluaGetWave( lua_State* L, int index );
REILUAPI Sound* uluaGetSound( lua_State* L, int index ); REILUAPI Sound* uluaGetSound( lua_State* L, int index );
REILUAPI Music* uluaGetMusic( lua_State* L, int index ); REILUAPI Music* uluaGetMusic( lua_State* L, int index );
REILUAPI AudioStream* uluaGetAudioStream( lua_State* L, int index );
REILUAPI Light* uluaGetLight( lua_State* L, int index ); REILUAPI Light* uluaGetLight( lua_State* L, int index );
REILUAPI Material* uluaGetMaterial( lua_State* L, int index ); REILUAPI Material* uluaGetMaterial( lua_State* L, int index );
REILUAPI Model* uluaGetModel( lua_State* L, int index ); REILUAPI Model* uluaGetModel( lua_State* L, int index );
@@ -123,6 +124,7 @@ REILUAPI void uluaPushWave( lua_State* L, Wave wave );
REILUAPI void uluaPushSound( lua_State* L, Sound sound ); REILUAPI void uluaPushSound( lua_State* L, Sound sound );
REILUAPI void uluaPushSoundAlias( lua_State* L, Sound alias ); REILUAPI void uluaPushSoundAlias( lua_State* L, Sound alias );
REILUAPI void uluaPushMusic( lua_State* L, Music music ); REILUAPI void uluaPushMusic( lua_State* L, Music music );
REILUAPI void uluaPushAudioStream( lua_State* L, AudioStream stream );
REILUAPI void uluaPushLight( lua_State* L, Light light ); REILUAPI void uluaPushLight( lua_State* L, Light light );
REILUAPI void uluaPushMaterial( lua_State* L, Material material ); REILUAPI void uluaPushMaterial( lua_State* L, Material material );
REILUAPI void uluaPushMesh( lua_State* L, Mesh mesh ); REILUAPI void uluaPushMesh( lua_State* L, Mesh mesh );
@@ -143,6 +145,7 @@ void uluaUnloadWave( Wave* wave );
void uluaUnloadSound( Sound* sound ); void uluaUnloadSound( Sound* sound );
void uluaUnloadSoundAlias( Sound* sound ); void uluaUnloadSoundAlias( Sound* sound );
void uluaUnloadMusic( Music* music ); void uluaUnloadMusic( Music* music );
void uluaUnloadAudioStream( AudioStream* stream );
void uluaUnloadMaterial( Material* material, bool freeAll ); void uluaUnloadMaterial( Material* material, bool freeAll );
void uluaUnloadMesh( Mesh* mesh ); void uluaUnloadMesh( Mesh* mesh );
void uluaUnloadModel( Model* model ); void uluaUnloadModel( Model* model );

View File

@@ -386,6 +386,21 @@ int laudioSetSoundPan( lua_State* L ) {
return 0; 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 ) > RL.WaveFormat( Wave wave, int sampleRate, int sampleSize, int channels )
@@ -716,3 +731,294 @@ int laudioGetMusicTimePlayed( lua_State* L ) {
return 1; 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;
}

View File

@@ -3821,7 +3821,11 @@ int lcoreSetBufferData( lua_State* L ) {
int len = uluaGetTableLen( L, 3 ); 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 ); TraceLog( state->logLevelInvalid, "SetBufferData. position %d out of bounds", position );
return 0; return 0;
} }

View File

@@ -254,6 +254,25 @@ static void defineMusic() {
lua_setfield( L, -2, "__gc" ); 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. */ /* Light. */
static void defineLight() { static void defineLight() {
lua_State* L = state->luaState; lua_State* L = state->luaState;
@@ -1341,6 +1360,7 @@ bool luaInit( int argn, const char** argc ) {
defineSound(); defineSound();
defineSoundAlias(); defineSoundAlias();
defineMusic(); defineMusic();
defineAudioStream();
defineLight(); defineLight();
defineMaterial(); defineMaterial();
defineMesh(); defineMesh();
@@ -2319,6 +2339,27 @@ void luaRegister() {
assingGlobalFunction( "GetMusicLooping", laudioGetMusicLooping ); assingGlobalFunction( "GetMusicLooping", laudioGetMusicLooping );
assingGlobalFunction( "GetMusicTimeLength", laudioGetMusicTimeLength ); assingGlobalFunction( "GetMusicTimeLength", laudioGetMusicTimeLength );
assingGlobalFunction( "GetMusicTimePlayed", laudioGetMusicTimePlayed ); 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. */ /* Math. */
/* Utils. */ /* 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 ) { Light* uluaGetLight( lua_State* L, int index ) {
switch ( lua_type( L, index ) ) { switch ( lua_type( L, index ) ) {
case LUA_TLIGHTUSERDATA: case LUA_TLIGHTUSERDATA:
@@ -4238,6 +4309,13 @@ void uluaPushMusic( lua_State* L, Music music ) {
luaL_setmetatable( L, "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 ) { void uluaPushLight( lua_State* L, Light light ) {
Light* lightP = lua_newuserdata( L, sizeof( Light ) ); Light* lightP = lua_newuserdata( L, sizeof( Light ) );
*lightP = light; *lightP = light;
@@ -4361,6 +4439,12 @@ void uluaUnloadMusic( Music* music ) {
memset( music, 0, sizeof( 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 ) { void uluaUnloadMaterial( Material* material, bool freeAll ) {
luaCallUnload( "Material", material ); luaCallUnload( "Material", material );
if ( freeAll ) { if ( freeAll ) {