Implement FlxSound.pan for stereo sounds

This commit is contained in:
Ralty
2025-11-02 15:46:42 +07:00
parent 4d73ec3477
commit 3a88e78cec
4 changed files with 93 additions and 22 deletions
@@ -251,16 +251,6 @@ class HTML5AudioSource
public function getPosition():Vector4
{
#if lime_howlerjs
// This should work, but it returns null (But checking the inside of the howl, the _pos is actually null... so ¯\_(ツ)_/¯)
/*
var arr = parent.buffer.__srcHowl.pos())
position.x = arr[0];
position.y = arr[1];
position.z = arr[2];
*/
#end
return position;
}
@@ -278,4 +268,16 @@ class HTML5AudioSource
return position;
}
public function getPan():Float
{
return position.x;
}
public function setPan(value:Float):Float
{
position.setTo(value, 0, -Math.sqrt(1 - value * value));
if (parent.buffer != null && parent.buffer.__srcHowl != null && parent.buffer.__srcHowl.stereo != null) parent.buffer.__srcHowl.stereo(value, id);
return value;
}
}
@@ -13,6 +13,7 @@ import lime.media.vorbis.Vorbis;
import lime.media.vorbis.VorbisFile;
#end
import lime.math.Vector2;
import lime.math.Vector4;
import lime.media.AudioBuffer;
import lime.media.AudioSource;
@@ -30,6 +31,11 @@ class NativeAudioSource {
private static var STREAM_TIMER_FREQUENCY:Int = 100;
private static var STREAM_BUFFER_FREQUENCY:Int = 3;
private static var moreFormatsSupported:Null<Bool>;
private static var stereoAnglesExtensionSupported:Null<Bool>;
private static var loopPointsSupported:Null<Bool>; // TODO: implement loop Points for looped static sources
private static var latencyExtensionSupported:Null<Bool>;
private var parent:AudioSource;
private var disposed:Bool;
private var streamed:Bool;
@@ -54,7 +60,9 @@ class NativeAudioSource {
private var streamEnded:Bool;
private var dataLength:Float;
private var position:Vector4 = new Vector4();
private var position:Vector4;
private var angles:Vector2;
private var anglesArray:Array<Float>;
private var length:Null<Float>;
private var loopTime:Null<Float>;
private var loops:Int;
@@ -65,6 +73,10 @@ class NativeAudioSource {
disposed = true;
stop();
position = null;
angles = null;
anglesArray = null;
if (handle != null) {
AL.sourcei(handle, AL.BUFFER, AL.NONE);
AL.deleteSource(handle);
@@ -81,16 +93,26 @@ class NativeAudioSource {
public function init() {
if (handle != null) return;
if (disposed = (handle = AL.createSource()) == null) return;
if (position == null) position = new Vector4();
if (angles == null) angles = new Vector2(Math.PI / 6, -Math.PI / 6); // https://github.com/kcat/openal-soft/issues/1032
anglesArray = [0, 0];
if (moreFormatsSupported == null) moreFormatsSupported = AL.isExtensionPresent("AL_EXT_MCFORMATS");
if (stereoAnglesExtensionSupported == null) stereoAnglesExtensionSupported = AL.isExtensionPresent("AL_EXT_STEREO_ANGLES");
if (latencyExtensionSupported == null) latencyExtensionSupported = AL.isExtensionPresent("AL_SOFT_source_latency");
if (loopPointsSupported == null) loopPointsSupported = AL.isExtensionPresent("AL_SOFT_loop_points");
AL.sourcef(handle, AL.MAX_GAIN, 10);
AL.distanceModel(AL.NONE);
var buffer = parent.buffer;
var channels = buffer.channels, bitsPerSample = buffer.bitsPerSample;
// Default is just AL.FORMAT_MONO8 if it doesn't match any to avoid yo ears getting blasted
var isCreativeXFi = AL.getString(AL.RENDERER) == "X-Fi";
if (channels > 2 && (isCreativeXFi || AL.isExtensionPresent("AL_EXT_MCFORMATS"))) { // https://github.com/openalext/openalext/blob/master/AL_EXT_MCFORMATS.txt
if (channels > 2 && (isCreativeXFi || moreFormatsSupported)) { // https://github.com/openalext/openalext/blob/master/AL_EXT_MCFORMATS.txt
if (channels == 3) format = bitsPerSample == 32 ? 0x1209 : (bitsPerSample == 16 ? 0x1208 : 0x1207);
else if (channels == 4) format = bitsPerSample == 32 ? 0x1206 : (bitsPerSample == 16 ? 0x1205 : 0x1204);
else if (channels == 6) format = bitsPerSample == 32 ? 0x120C : (bitsPerSample == 16 ? 0x120B : 0x120A);
@@ -466,7 +488,7 @@ class NativeAudioSource {
public function getLatency():Float {
/*#if (lime >= "8.3.0")
if (AL.isExtensionPresent("AL_SOFT_source_latency")) {
if (latencyExtensionSupported) {
final offsets = AL.getSourcedvSOFT(handle, AL.SEC_OFFSET_LATENCY_SOFT, 2);
if (offsets != null) return offsets[1] * 1000;
}
@@ -474,7 +496,28 @@ class NativeAudioSource {
return 0;
}
public function getPosition():Vector4 return position;
public function getAngles():Vector2 {
if (angles == null) angles = new Vector2(Math.PI / 6, -Math.PI / 6);
return angles;
}
public function setAngles(left:Float, right:Float):Vector2 {
if (angles == null) angles = new Vector2(left, right);
else angles.setTo(left, right);
if (!disposed) {
anglesArray[0] = angles.x;
anglesArray[1] = angles.y;
AL.sourcei(handle, 0x1214/*AL.SOURCE_SPATIALIZE_SOFT*/, AL.FALSE);
AL.sourcefv(handle, 0x1030/*AL.STEREO_ANGLES*/, anglesArray);
}
return angles;
}
public function getPosition():Vector4 {
if (position == null) position = new Vector4();
return position;
}
public function setPosition(value:Vector4):Vector4 {
position.x = value.x;
@@ -482,13 +525,28 @@ class NativeAudioSource {
position.z = value.z;
position.w = value.w;
// OpenAL Soft Positions doesn't seem to do anything but panning?
if (!disposed) {
AL.distanceModel(AL.NONE);
AL.sourcei(handle, 0x1214/*AL.SOURCE_SPATIALIZE_SOFT*/, Math.abs(position.x) > 1e-04 ? AL.TRUE : AL.FALSE);
AL.sourcei(handle, AL.MAX_DISTANCE, 1);
AL.source3f(handle, AL.POSITION, position.x, position.y, position.z);
}
return position;
}
public function getPan():Float return getPosition().x;
public function setPan(value:Float):Float {
getPosition().setTo(value, 0, -Math.sqrt(1 - value * value));
if (!disposed) {
if (parent.buffer.channels > 1 && stereoAnglesExtensionSupported)
setAngles(Math.PI * (Math.min(-value * 2 + 1, 1)) / 6, -Math.PI * Math.min(value * 2 + 1, 1) / 6);
else
setPosition(position);
}
return value;
}
inline private function getFloat(x:Int64):Float return x.high * 4294967296. + (x.low >> 0);
inline private function getSamples(ms:Float):Int64 return Int64.fromFloat(Math.max(0, Math.min(ms / 1000 * parent.buffer.sampleRate, samples)));
}
+15
View File
@@ -80,6 +80,11 @@ class AudioSource
**/
public var position(get, set):Vector4;
/**
The stereo pan of the audio source.
**/
public var pan(get, set):Float;
/**
The latency of the audio source.
**/
@@ -229,6 +234,16 @@ class AudioSource
return __backend.setPosition(value);
}
@:noCompletion inline private function get_pan():Float
{
return __backend.getPan();
}
@:noCompletion inline private function set_pan(value:Float):Float
{
return __backend.setPan(value);
}
@:noCompletion inline private function get_latency():Float
{
return __backend.getLatency();
+2 -6
View File
@@ -273,13 +273,9 @@ import lime.media.openal.AL;
if (__isValid)
{
#if lime
// TODO: implement SoundTransform.leftToRight, etc. with Native setAngles?
__source.gain = volume;
var position = __source.position;
position.x = pan;
position.z = -1 * Math.sqrt(1 - Math.pow(pan, 2));
__source.position = position;
__source.pan = pan;
return value;
#end
}