11package lime ._internal .backend .native ;
22
3+ import sys .thread .Thread ;
4+ import sys .thread .Mutex ;
5+
36import haxe .Timer ;
47import haxe .Int64 ;
58
9+ import lime .app .Application ;
610import lime .media .openal .AL ;
711import lime .media .openal .ALBuffer ;
812import lime .media .openal .ALSource ;
@@ -23,11 +27,6 @@ import lime.utils.ArrayBuffer;
2327import lime .utils .ArrayBufferView .TypedArrayType ;
2428import lime .utils .ArrayBufferView ;
2529
26- #if audio_stream_async
27- import sys .thread .Thread ;
28- import sys .thread .Mutex ;
29- #end
30-
3130#if !lime_debug
3231@:fileXml (' tags="haxe,release"' )
3332@:noDebug
@@ -43,7 +42,6 @@ class NativeAudioSource {
4342 public static var STREAM_MAX_BUFFERS : Int = 8 ; // how much limit of a buffers can be used for streamed audios, must be higher than minimum.
4443 public static var STREAM_FLUSH_BUFFERS : Int = 3 ; // how much buffers can it play.
4544 public static var STREAM_PROCESS_BUFFERS : Int = 2 ; // how much buffers can be processed in a frequency tick.
46- public static var STREAM_TIMER_CHECK_MS : Int = 100 ; // determines how milliseconds to update the buffers if available.
4745 public static var MAX_POOL_BUFFERS : Int = 32 ; // how much buffers for the pool to hold.
4846
4947 public static var moreFormatsSupported : Null <Bool >;
@@ -89,6 +87,14 @@ class NativeAudioSource {
8987
9088 inline private static function getFloat (x : Int64 ): Float return x .high * 4294967296. + (x .low >> 0);
9189
90+ inline private static function gc () {
91+ #if neko
92+ neko.vm. Gc .run (false );
93+ #elseif cpp
94+ cpp.vm. Gc .run (false );
95+ #end
96+ }
97+
9298 // Backward Compatibility Variables
9399 var handle (get , set ): ALSource ; inline function get_handle () return source ; inline function set_handle (v ) return source = v ;
94100 var timer (get , set ): Timer ; inline function get_timer () return completeTimer ; inline function set_timer (v ) return completeTimer = v ;
@@ -125,19 +131,14 @@ class NativeAudioSource {
125131 var arrayType : TypedArrayType ;
126132 var loopPoints : Array <Int >; // In Samples
127133
128- #if audio_stream_async
129134 static var threadRunning : Bool = false ;
130135 static var streamSources : Array <NativeAudioSource > = [];
131136 static var queuedStreamSources : Array <NativeAudioSource > = [];
132137
133- static var streamHandlerTimer : Timer ;
134138 static var streamMutex : Mutex = new Mutex ();
135139 static var streamThread : Thread ;
136140
137141 var streamRemove : Bool ;
138- #else
139- var streamTimer : Timer ;
140- #end
141142
142143 var bufferLength : Int ; // Size in bytes for current streamed audio buffers.
143144 var requestBuffers : Int ;
@@ -162,10 +163,8 @@ class NativeAudioSource {
162163 }
163164
164165 public function dispose () {
165- #if audio_stream_async
166166 streamMutex .acquire ();
167167 removeStream ();
168- #end
169168
170169 stop ();
171170 disposed = true ;
@@ -201,12 +200,11 @@ class NativeAudioSource {
201200 }
202201
203202 completeTimer = null ;
204- #if !audio_stream_async streamTimer = null ; #end
205203
206204 bufferTimes = null ;
207205 bufferLengths = null ;
208206
209- #if audio_stream_async streamMutex .release (); #end
207+ streamMutex .release ();
210208 }
211209
212210 public function init () {
@@ -225,17 +223,15 @@ class NativeAudioSource {
225223 public function resetBuffer () {
226224 if (parent .buffer == null ) return ;
227225
228- #if audio_stream_async
229226 streamMutex .acquire ();
230227 removeStream ();
231- #end
232228
233229 stop ();
234230
235231 if (streamed ) AL .sourceUnqueueBuffers (source , AL .getSourcei (source , AL .BUFFERS_QUEUED ));
236232 else AL .sourcei (source , AL .BUFFER , AL .NONE );
237233
238- #if audio_stream_async streamMutex .release (); #end
234+ streamMutex .release ();
239235
240236 final audioBuffer = parent .buffer ;
241237 channels = audioBuffer .channels ;
@@ -456,7 +452,7 @@ class NativeAudioSource {
456452 function snapBuffersToTime (time : Float , force : Bool ) {
457453 if (source == null || parent .buffer == null || parent .buffer .__srcVorbisFile == null ) return ;
458454
459- #if audio_stream_async streamMutex .acquire (); #end
455+ streamMutex .acquire ();
460456
461457 final sec = time / 1000 ;
462458 if (! force ) {
@@ -466,8 +462,7 @@ class NativeAudioSource {
466462 {
467463 skipBuffers (i - STREAM_MAX_BUFFERS + requestBuffers );
468464 AL .sourcei (source , AL .SAMPLE_OFFSET , Math .floor ((sec - bufferTime ) * sampleRate ));
469- #if audio_stream_async streamMutex .release (); #end
470- return ;
465+ return streamMutex .release ();
471466 }
472467 }
473468
@@ -479,10 +474,9 @@ class NativeAudioSource {
479474 requestBuffers = queuedBuffers = streamLoops = nextBuffer = 0 ;
480475 fillBuffers (STREAM_MIN_BUFFERS );
481476 flushBuffers ();
482- #if audio_stream_async streamMutex .release (); #end
477+ streamMutex .release ();
483478 }
484479
485- #if audio_stream_async
486480 static function streamThreadRun () {
487481 var i : Int , source : NativeAudioSource , process : Int , v : Int ;
488482
@@ -500,39 +494,48 @@ class NativeAudioSource {
500494 if ((process = (v = STREAM_MAX_BUFFERS - source .requestBuffers ) > process ? process : v ) > 0 ) source .fillBuffers (process );
501495 }
502496 streamMutex .release ();
497+ gc ();
503498 }
504499
505500 threadRunning = false ;
506501 }
507502
508- static function streamHandlerRun ( ) {
509- if ( ! streamMutex .tryAcquire ()) return ;
503+ static function streamUpdate ( _ : Int ) {
504+ final acquired = streamMutex .tryAcquire ();
510505
511506 var i = queuedStreamSources .length , source : NativeAudioSource ;
512507 while (i -- > 0 ) streamSources .push (queuedStreamSources [i ]);
513508 queuedStreamSources .resize (0 );
514509
515510 i = streamSources .length ;
516511 while (i -- > 0 ) {
517- if ((source = streamSources [i ]).streamRemove || source .source == null )
518- source .removeStream ();
512+ if ((source = streamSources [i ]).streamRemove ) {
513+ if (acquired ) source .removeStream ();
514+ else continue ;
515+ }
516+ else if (source .source == null ) {
517+ if (acquired ) source .removeStream ();
518+ else source .stopStream ();
519+ }
519520 else {
520- source .skipBuffers (AL .getSourcei (source .source , AL .BUFFERS_PROCESSED ));
521+ if ( acquired ) source .skipBuffers (AL .getSourcei (source .source , AL .BUFFERS_PROCESSED ));
521522 source .flushBuffers ();
522-
523523 if (AL .getSourcei (source .source , AL .SOURCE_STATE ) == AL .STOPPED ) {
524524 AL .sourcePlay (source .source );
525525 source .updateCompleteTimer ();
526526 }
527- if (source .streamEnded ) source .removeStream ();
528527 }
529528 }
530529
531- streamMutex .release ();
532-
533- if (streamSources .length == 0 ) streamHandlerTimer .stop ();
534- else if (threadRunning || (threadRunning = (streamThread = Thread .create (streamThreadRun )) != null ))
535- streamThread .sendMessage (streamSources .length );
530+ if (acquired ) {
531+ streamMutex .release ();
532+ if (streamSources .length == 0 ) {
533+ Application .current .onUpdate .remove (streamUpdate );
534+ if (threadRunning ) streamThread .sendMessage (0 );
535+ }
536+ else if (threadRunning || (threadRunning = (streamThread = Thread .create (streamThreadRun )) != null ))
537+ streamThread .sendMessage (streamSources .length );
538+ }
536539 }
537540
538541 function removeStream () {
@@ -550,36 +553,10 @@ class NativeAudioSource {
550553 streamRemove = false ;
551554 if (! queuedStreamSources .contains (this ) && ! streamSources .contains (this )) {
552555 queuedStreamSources .push (this );
553- if (streamHandlerTimer == null || ! streamHandlerTimer .mRunning )
554- streamHandlerTimer = resetTimer (streamHandlerTimer , STREAM_TIMER_CHECK_MS , streamHandlerRun );
555- }
556- }
557- #else
558- function streamRun () {
559- if (source == null || parent .buffer == null || parent .buffer .__srcVorbisFile == null )
560- return streamTimer .stop ();
561-
562- skipBuffers (AL .getSourcei (source , AL .BUFFERS_PROCESSED ));
563-
564- var process = requestBuffers < STREAM_MIN_BUFFERS ? STREAM_MIN_BUFFERS - requestBuffers : 0 , v = STREAM_MAX_BUFFERS - requestBuffers ;
565- process = STREAM_PROCESS_BUFFERS > process ? STREAM_PROCESS_BUFFERS : process ;
566- if ((process = v > process ? process : v ) > 0 ) fillBuffers (process );
567- flushBuffers ();
568-
569- if (AL .getSourcei (source , AL .SOURCE_STATE ) == AL .STOPPED ) {
570- AL .sourcePlay (source );
571- updateCompleteTimer ();
556+ if (! Application .current .onUpdate .has (streamUpdate )) Application .current .onUpdate .add (streamUpdate );
572557 }
573- if (streamEnded ) streamTimer .stop ();
574558 }
575559
576- function stopStream () if (streamTimer != null ) streamTimer .stop ();
577-
578- function resetStream ()
579- if (streamTimer == null || ! streamTimer .mRunning )
580- streamTimer = resetTimer (streamTimer , STREAM_TIMER_CHECK_MS , streamRun );
581- #end
582-
583560 function timer_onRun () {
584561 final pitch = getPitch ();
585562 var timeRemaining = (getLength () - getCurrentTime ()) / pitch ;
0 commit comments