diff --git a/project/src/media/openal/OpenALBindings.cpp b/project/src/media/openal/OpenALBindings.cpp index fe549149df..4dec09027d 100644 --- a/project/src/media/openal/OpenALBindings.cpp +++ b/project/src/media/openal/OpenALBindings.cpp @@ -2104,6 +2104,44 @@ namespace lime { } + value lime_al_get_sourcedv_soft (value source, int param, int count) { + + #ifdef LIME_OPENALSOFT + ALuint id = (ALuint)(uintptr_t)val_data (source); + ALdouble* values = new ALdouble[count]; + alGetSourcedvSOFT (id, param, values); + + value result = alloc_array (count); + + for (int i = 0; i < count; i++) { + + val_array_set_i (result, i, alloc_float (values[i])); + + } + + delete[] values; + return result; + #else + return alloc_null(); + #endif + + } + + + HL_PRIM varray* HL_NAME(hl_al_get_sourcedv_soft) (HL_CFFIPointer* source, int param, int count) { + + #ifdef LIME_OPENALSOFT + ALuint id = (ALuint)(uintptr_t)source->ptr; + varray* result = hl_alloc_array (&hlt_f64, count); + alGetSourcedvSOFT (id, param, hl_aptr (result, double)); + return result; + #else + return NULL; + #endif + + } + + value lime_al_get_sourcei (value source, int param) { ALuint id = (ALuint)(uintptr_t)val_data (source); @@ -3579,6 +3617,7 @@ namespace lime { DEFINE_PRIME2 (lime_al_get_source3i); DEFINE_PRIME2 (lime_al_get_sourcef); DEFINE_PRIME3 (lime_al_get_sourcefv); + DEFINE_PRIME3 (lime_al_get_sourcedv_soft); DEFINE_PRIME2 (lime_al_get_sourcei); DEFINE_PRIME3 (lime_al_get_sourceiv); DEFINE_PRIME1 (lime_al_get_string); @@ -3703,6 +3742,7 @@ namespace lime { DEFINE_HL_PRIM (_ARR, hl_al_get_source3i, _TCFFIPOINTER _I32); DEFINE_HL_PRIM (_F32, hl_al_get_sourcef, _TCFFIPOINTER _I32); DEFINE_HL_PRIM (_ARR, hl_al_get_sourcefv, _TCFFIPOINTER _I32 _I32); + DEFINE_HL_PRIM (_ARR, hl_al_get_sourcedv_soft, _TCFFIPOINTER _I32 _I32); DEFINE_HL_PRIM (_DYN, hl_al_get_sourcei, _TCFFIPOINTER _I32); DEFINE_HL_PRIM (_ARR, hl_al_get_sourceiv, _TCFFIPOINTER _I32 _I32); DEFINE_HL_PRIM (_BYTES, hl_al_get_string, _I32); diff --git a/src/lime/_internal/backend/flash/FlashAudioSource.hx b/src/lime/_internal/backend/flash/FlashAudioSource.hx index 1d1f10c9ca..96b8c5410c 100644 --- a/src/lime/_internal/backend/flash/FlashAudioSource.hx +++ b/src/lime/_internal/backend/flash/FlashAudioSource.hx @@ -148,4 +148,9 @@ class FlashAudioSource return position; } + + public function getLatency():Float + { + return 0; + } } diff --git a/src/lime/_internal/backend/html5/HTML5AudioSource.hx b/src/lime/_internal/backend/html5/HTML5AudioSource.hx index f2b9fe80b2..9657487c43 100644 --- a/src/lime/_internal/backend/html5/HTML5AudioSource.hx +++ b/src/lime/_internal/backend/html5/HTML5AudioSource.hx @@ -1,5 +1,6 @@ package lime._internal.backend.html5; +import lime.media.AudioManager; import lime.math.Vector4; import lime.media.AudioSource; @@ -267,4 +268,18 @@ class HTML5AudioSource return position; } + + public function getLatency():Float + { + var ctx = AudioManager.context.web; + if (ctx != null) + { + var baseLatency:Float = untyped ctx.baseLatency != null ? untyped ctx.baseLatency : 0; + var outputLatency:Float = untyped ctx.outputLatency != null ? untyped ctx.outputLatency : 0; + + return (baseLatency + outputLatency) * 1000; + } + + return 0; + } } diff --git a/src/lime/_internal/backend/native/NativeAudioSource.hx b/src/lime/_internal/backend/native/NativeAudioSource.hx index ab85e0e002..1d228bd7a7 100644 --- a/src/lime/_internal/backend/native/NativeAudioSource.hx +++ b/src/lime/_internal/backend/native/NativeAudioSource.hx @@ -26,6 +26,10 @@ class NativeAudioSource #end private static var STREAM_TIMER_FREQUENCY = 100; + #if lime_openalsoft + private static var hasALSoftLatencyExt:Null; + #end + private var buffers:Array; private var bufferTimeBlocks:Array; private var completed:Bool; @@ -70,6 +74,13 @@ class NativeAudioSource public function init():Void { + #if lime_openalsoft + if (hasALSoftLatencyExt == null) + { + hasALSoftLatencyExt = AL.isExtensionPresent("AL_SOFT_source_latency"); + } + #end + dataLength = 0; format = 0; @@ -588,4 +599,20 @@ class NativeAudioSource return position; } + + public function getLatency():Float + { + #if lime_openalsoft + if (hasALSoftLatencyExt) + { + var offsets = AL.getSourcedvSOFT(handle, AL.SEC_OFFSET_LATENCY_SOFT, 2); + if (offsets != null) + { + return offsets[1] * 1000; + } + } + #end + + return 0; + } } diff --git a/src/lime/_internal/backend/native/NativeCFFI.hx b/src/lime/_internal/backend/native/NativeCFFI.hx index aae8999232..5b20d55dbe 100644 --- a/src/lime/_internal/backend/native/NativeCFFI.hx +++ b/src/lime/_internal/backend/native/NativeCFFI.hx @@ -1607,6 +1607,8 @@ class NativeCFFI @:cffi private static function lime_al_get_sourcefv(source:CFFIPointer, param:Int, count:Int):Array; + @:cffi private static function lime_al_get_sourcedv_soft(source:CFFIPointer, param:Int, count:Int):Array; + @:cffi private static function lime_al_get_sourcei(source:CFFIPointer, param:Int):Dynamic; @:cffi private static function lime_al_get_sourceiv(source:CFFIPointer, param:Int, count:Int):Array; @@ -1797,6 +1799,8 @@ class NativeCFFI private static var lime_al_get_sourcef = new cpp.CallableInt->cpp.Float32>(cpp.Prime._loadPrime("lime", "lime_al_get_sourcef", "oif", false)); private static var lime_al_get_sourcefv = new cpp.CallableInt->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_sourcefv", "oiio", false)); + private static var lime_al_get_sourcedv_soft = new cpp.CallableInt->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_sourcedv_soft", "oiio", + false)); private static var lime_al_get_sourcei = new cpp.CallableInt->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_sourcei", "oio", false)); private static var lime_al_get_sourceiv = new cpp.CallableInt->Int->cpp.Object>(cpp.Prime._loadPrime("lime", "lime_al_get_sourceiv", "oiio", false)); @@ -1938,6 +1942,7 @@ class NativeCFFI private static var lime_al_get_source3i = CFFI.load("lime", "lime_al_get_source3i", 2); private static var lime_al_get_sourcef = CFFI.load("lime", "lime_al_get_sourcef", 2); private static var lime_al_get_sourcefv = CFFI.load("lime", "lime_al_get_sourcefv", 3); + private static var lime_al_get_sourcedv_soft = CFFI.load("lime", "lime_al_get_sourcedv_soft", 3); private static var lime_al_get_sourcei = CFFI.load("lime", "lime_al_get_sourcei", 2); private static var lime_al_get_sourceiv = CFFI.load("lime", "lime_al_get_sourceiv", 3); private static var lime_al_get_string = CFFI.load("lime", "lime_al_get_string", 1); @@ -2195,6 +2200,11 @@ class NativeCFFI return null; } + @:hlNative("lime", "hl_al_get_sourcedv_soft") private static function lime_al_get_sourcedv_soft(source:CFFIPointer, param:Int, count:Int):hl.NativeArray + { + return null; + } + @:hlNative("lime", "hl_al_get_sourcei") private static function lime_al_get_sourcei(source:CFFIPointer, param:Int):Dynamic { return null; diff --git a/src/lime/media/AudioSource.hx b/src/lime/media/AudioSource.hx index 2ccc9b1465..09098ea669 100644 --- a/src/lime/media/AudioSource.hx +++ b/src/lime/media/AudioSource.hx @@ -10,8 +10,8 @@ import lime.math.Vector4; @:noDebug #end /** - The `AudioSource` class provides a way to control audio playback in a Lime application. - It allows for playing, pausing, and stopping audio, as well as controlling various + The `AudioSource` class provides a way to control audio playback in a Lime application. + It allows for playing, pausing, and stopping audio, as well as controlling various audio properties such as gain, pitch, and looping. Depending on the platform, the audio backend may vary, but the API remains consistent. @@ -24,7 +24,7 @@ class AudioSource An event that is dispatched when the audio playback is complete. **/ public var onComplete = new EventVoid>(); - + /** The `AudioBuffer` associated with this `AudioSource`. **/ @@ -65,6 +65,11 @@ class AudioSource **/ public var position(get, set):Vector4; + /** + The estimated output latency, in miliseconds, for this `AudioSource`. If not possible to retrieve will return `0`. + **/ + public var latency(get, never):Float; + @:noCompletion private var __backend:AudioSourceBackend; /** @@ -191,6 +196,11 @@ class AudioSource { return __backend.setPosition(value); } + + @:noCompletion private function get_latency():Float + { + return __backend.getLatency(); + } } #if flash diff --git a/src/lime/media/OpenALAudioContext.hx b/src/lime/media/OpenALAudioContext.hx index d731f72397..831682748d 100644 --- a/src/lime/media/OpenALAudioContext.hx +++ b/src/lime/media/OpenALAudioContext.hx @@ -388,7 +388,16 @@ class OpenALAudioContext public function getSourcefv(source:ALSource, param:Int, count:Int = 1):Array { - return AL.getSourcefv(source, param); + return AL.getSourcefv(source, param, count); + } + + public function getSourcedvSOFT(source:ALSource, param:Int, count:Int = 1):Array + { + #if lime_openalsoft + return AL.getSourcedvSOFT(source, param, count); + #end + + return null; } public function getSourcei(source:ALSource, param:Int):Dynamic diff --git a/src/lime/media/openal/AL.hx b/src/lime/media/openal/AL.hx index f1bcdb7a33..1e12bcd52c 100644 --- a/src/lime/media/openal/AL.hx +++ b/src/lime/media/openal/AL.hx @@ -233,6 +233,9 @@ class AL public static inline var FILTER_LOWPASS:Int = 0x0001; public static inline var FILTER_HIGHPASS:Int = 0x0002; public static inline var FILTER_BANDPASS:Int = 0x0003; + /* AL_SOFT_source_latency extension */ + public static inline var SAMPLE_OFFSET_LATENCY_SOFT = 0x1200; + public static inline var SEC_OFFSET_LATENCY_SOFT = 0x1201; public static function removeDirectFilter(source:ALSource) { @@ -969,6 +972,24 @@ class AL #end } + public static function getSourcedvSOFT(source:ALSource, param:Int, count:Int = 1):Array + { + #if (lime_cffi && lime_openalsoft && !macro) + var result = NativeCFFI.lime_al_get_sourcedv_soft(source, param, count); + #if hl + if (result == null) return []; + var _result:Array = []; + for (i in 0...result.length) + _result[i] = result[i]; + return _result; + #else + return result; + #end + #else + return null; + #end + } + public static function getSourcei(source:ALSource, param:Int):Dynamic { #if (lime_cffi && lime_openal && !macro)