@@ -13,6 +13,7 @@ import lime.media.vorbis.Vorbis;
1313import lime .media .vorbis .VorbisFile ;
1414#end
1515
16+ import lime .math .Vector2 ;
1617import lime .math .Vector4 ;
1718import lime .media .AudioBuffer ;
1819import lime .media .AudioSource ;
@@ -30,6 +31,11 @@ class NativeAudioSource {
3031 private static var STREAM_TIMER_FREQUENCY : Int = 100 ;
3132 private static var STREAM_BUFFER_FREQUENCY : Int = 3 ;
3233
34+ private static var moreFormatsSupported : Null <Bool >;
35+ private static var stereoAnglesExtensionSupported : Null <Bool >;
36+ private static var loopPointsSupported : Null <Bool >; // TODO: implement loop Points for looped static sources
37+ private static var latencyExtensionSupported : Null <Bool >;
38+
3339 private var parent : AudioSource ;
3440 private var disposed : Bool ;
3541 private var streamed : Bool ;
@@ -54,7 +60,9 @@ class NativeAudioSource {
5460 private var streamEnded : Bool ;
5561 private var dataLength : Float ;
5662
57- private var position : Vector4 = new Vector4 ();
63+ private var position : Vector4 ;
64+ private var angles : Vector2 ;
65+ private var anglesArray : Array <Float >;
5866 private var length : Null <Float >;
5967 private var loopTime : Null <Float >;
6068 private var loops : Int ;
@@ -65,6 +73,10 @@ class NativeAudioSource {
6573 disposed = true ;
6674 stop ();
6775
76+ position = null ;
77+ angles = null ;
78+ anglesArray = null ;
79+
6880 if (handle != null ) {
6981 AL .sourcei (handle , AL .BUFFER , AL .NONE );
7082 AL .deleteSource (handle );
@@ -81,16 +93,26 @@ class NativeAudioSource {
8193
8294 public function init () {
8395 if (handle != null ) return ;
84-
8596 if (disposed = (handle = AL .createSource ()) == null ) return ;
97+
98+ if (position == null ) position = new Vector4 ();
99+ if (angles == null ) angles = new Vector2 (Math .PI / 6 , - Math .PI / 6 ); // https://github.com/kcat/openal-soft/issues/1032
100+ anglesArray = [0 , 0 ];
101+
102+ if (moreFormatsSupported == null ) moreFormatsSupported = AL .isExtensionPresent (" AL_EXT_MCFORMATS" );
103+ if (stereoAnglesExtensionSupported == null ) stereoAnglesExtensionSupported = AL .isExtensionPresent (" AL_EXT_STEREO_ANGLES" );
104+ if (latencyExtensionSupported == null ) latencyExtensionSupported = AL .isExtensionPresent (" AL_SOFT_source_latency" );
105+ if (loopPointsSupported == null ) loopPointsSupported = AL .isExtensionPresent (" AL_SOFT_loop_points" );
106+
86107 AL .sourcef (handle , AL .MAX_GAIN , 10 );
108+ AL .distanceModel (AL .NONE );
87109
88110 var buffer = parent .buffer ;
89111 var channels = buffer .channels , bitsPerSample = buffer .bitsPerSample ;
90112
91113 // Default is just AL.FORMAT_MONO8 if it doesn't match any to avoid yo ears getting blasted
92114 var isCreativeXFi = AL .getString (AL .RENDERER ) == " X-Fi" ;
93- if (channels > 2 && (isCreativeXFi || AL . isExtensionPresent ( " AL_EXT_MCFORMATS " ) )) { // https://github.com/openalext/openalext/blob/master/AL_EXT_MCFORMATS.txt
115+ if (channels > 2 && (isCreativeXFi || moreFormatsSupported )) { // https://github.com/openalext/openalext/blob/master/AL_EXT_MCFORMATS.txt
94116 if (channels == 3 ) format = bitsPerSample == 32 ? 0x1209 : (bitsPerSample == 16 ? 0x1208 : 0x1207 );
95117 else if (channels == 4 ) format = bitsPerSample == 32 ? 0x1206 : (bitsPerSample == 16 ? 0x1205 : 0x1204 );
96118 else if (channels == 6 ) format = bitsPerSample == 32 ? 0x120C : (bitsPerSample == 16 ? 0x120B : 0x120A );
@@ -466,29 +488,65 @@ class NativeAudioSource {
466488
467489 public function getLatency (): Float {
468490 /* #if (lime >= "8.3.0")
469- if (AL.isExtensionPresent("AL_SOFT_source_latency") ) {
491+ if (latencyExtensionSupported ) {
470492 final offsets = AL.getSourcedvSOFT(handle, AL.SEC_OFFSET_LATENCY_SOFT, 2);
471493 if (offsets != null) return offsets[1] * 1000;
472494 }
473495 #end*/
474496 return 0 ;
475497 }
476498
477- public function getPosition (): Vector4 return position ;
499+ public function getAngles (): Vector2 {
500+ if (angles == null ) angles = new Vector2 (Math .PI / 6 , - Math .PI / 6 );
501+ return angles ;
502+ }
503+
504+ public function setAngles (left : Float , right : Float ): Vector2 {
505+ if (angles == null ) angles = new Vector2 (left , right );
506+ else angles .setTo (left , right );
507+
508+ if (! disposed ) {
509+ anglesArray [0 ] = angles .x ;
510+ anglesArray [1 ] = angles .y ;
511+ AL .sourcei (handle , 0x1214 /* AL.SOURCE_SPATIALIZE_SOFT*/ , AL .FALSE );
512+ AL .sourcefv (handle , 0x1030 /* AL.STEREO_ANGLES*/ , anglesArray );
513+ }
514+ return angles ;
515+ }
516+
517+ public function getPosition (): Vector4 {
518+ if (position == null ) position = new Vector4 ();
519+ return position ;
520+ }
478521
479522 public function setPosition (value : Vector4 ): Vector4 {
480523 position .x = value .x ;
481524 position .y = value .y ;
482525 position .z = value .z ;
483526 position .w = value .w ;
484527
528+ // OpenAL Soft Positions doesn't seem to do anything but panning?
485529 if (! disposed ) {
486- AL .distanceModel (AL .NONE );
530+ AL .sourcei (handle , 0x1214 /* AL.SOURCE_SPATIALIZE_SOFT*/ , Math .abs (position .x ) > 1e-04 ? AL .TRUE : AL .FALSE );
531+ AL .sourcei (handle , AL .MAX_DISTANCE , 1 );
487532 AL .source3f (handle , AL .POSITION , position .x , position .y , position .z );
488533 }
489534 return position ;
490535 }
491536
537+ public function getPan (): Float return getPosition ().x ;
538+
539+ public function setPan (value : Float ): Float {
540+ getPosition ().setTo (value , 0 , - Math .sqrt (1 - value * value ));
541+ if (! disposed ) {
542+ if (parent .buffer .channels > 1 && stereoAnglesExtensionSupported )
543+ setAngles (Math .PI * (Math .min (- value * 2 + 1 , 1 )) / 6 , - Math .PI * Math .min (value * 2 + 1 , 1 ) / 6 );
544+ else
545+ setPosition (position );
546+ }
547+ return value ;
548+ }
549+
492550 inline private function getFloat (x : Int64 ): Float return x .high * 4294967296. + (x .low >> 0);
493551 inline private function getSamples (ms : Float ): Int64 return Int64 .fromFloat (Math .max (0 , Math .min (ms / 1000 * parent .buffer .sampleRate , samples )));
494552}
0 commit comments