Update Audio Backend from Vs Camellia v2.75.1 (info at desc)
Before anyone asks why vs cam, the code is public, plus i helped most of the audio backend rewrite in the mod too. :P - Static sounds can now also seamlessly loop with AL_SOFT_loop_points extension - Panning stereo sounds is now possible with AL_EXT_STEREO_ANGLES extension (although this was already implemented before) - Improved streaming sounds, should fix most of the lagspike issues - Streaming sounds should no longer regenrate if it's in the nearest timestamp (not for reversing though) ! You still can't access FlxSound.latency because of the new procedures that's not available in lime If there's any crashes with this pls report an issue asap.
This commit is contained in:
+9
-6
@@ -1,14 +1,17 @@
|
||||
[general]
|
||||
[General]
|
||||
sample-type=float32
|
||||
stereo-mode=speakers
|
||||
stereo-encoding=panpot
|
||||
hrtf=false
|
||||
cf_level=0
|
||||
resampler=fast_bsinc24
|
||||
front-stablizer=false
|
||||
output-limiter=false
|
||||
front-stabilizer=false
|
||||
volume-adjust=0
|
||||
period_size=441
|
||||
sources=512
|
||||
sends=64
|
||||
dither=false
|
||||
|
||||
[decoder]
|
||||
hq-mode=false
|
||||
distance-comp=false
|
||||
hq-mode=true
|
||||
distance-comp=true
|
||||
nfc=false
|
||||
@@ -718,7 +718,7 @@ class FlxSound extends FlxBasic {
|
||||
_paused = false;
|
||||
_time = startTime;
|
||||
_lastTime = FlxG.game.getTicks();
|
||||
if (_channel == null || !_channel.__isValid || _source == null #if lime_cffi || _source.__backend.disposed || _source.__backend.handle == null #end)
|
||||
if (_channel == null || !_channel.__isValid || _source == null #if lime_cffi || _source.__backend.disposed #end)
|
||||
makeChannel();
|
||||
|
||||
if (_channel != null) {
|
||||
@@ -939,19 +939,19 @@ class FlxSound extends FlxBasic {
|
||||
return _time = time;
|
||||
}
|
||||
|
||||
inline function get_offset():Float return _offset;
|
||||
inline function set_offset(offset:Float):Float {
|
||||
function get_offset():Float return _offset;
|
||||
function set_offset(offset:Float):Float {
|
||||
if (_offset == (_offset = offset)) return offset;
|
||||
//time = time + _offset;
|
||||
return offset;
|
||||
}
|
||||
|
||||
inline function get_length():Float return _length - _offset;
|
||||
function get_length():Float return _length - _offset;
|
||||
|
||||
/*function get_latency():Float {
|
||||
if (_channel != null) return _source.latency;
|
||||
return 0;
|
||||
}*/
|
||||
//function get_latency():Float {
|
||||
// if (_channel != null) return _source.latency;
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
override function toString():String {
|
||||
return FlxStringUtil.getDebugString([
|
||||
|
||||
@@ -20,8 +20,7 @@ typedef AudioAnalyzerCallback = Int->Int->Void;
|
||||
* An utility that analyze FlxSounds,
|
||||
* can be used to make waveform or real-time audio visualizer.
|
||||
*
|
||||
* FlxSound.amplitude does work in CNE so if any case if your only checking for peak of current
|
||||
* time, use that instead.
|
||||
* FlxSound.amplitude works so if any case if your only checking for peak of current time, use that instead.
|
||||
*/
|
||||
final class AudioAnalyzer {
|
||||
/**
|
||||
@@ -296,7 +295,7 @@ final class AudioAnalyzer {
|
||||
__check();
|
||||
}
|
||||
|
||||
function __check() if (sound.buffer != buffer) {
|
||||
function __check() if (sound != null && sound.buffer != buffer) {
|
||||
byteSize = 1 << ((buffer = sound.buffer).bitsPerSample - 1);
|
||||
|
||||
#if (lime_cffi && lime_vorbis)
|
||||
@@ -324,7 +323,7 @@ final class AudioAnalyzer {
|
||||
* @param maxFreq The maximum frequency to cap (Optional, default 22000.0, Above 23000.0 is not recommended).
|
||||
* @return Output of levels/bars that ranges from 0 to 1.
|
||||
*/
|
||||
public function getLevels(startPos:Float, ?volume:Float, barCount:Int, ?levels:Array<Float>, ?ratio:Float, ?minDb:Float, ?maxDb:Float, ?minFreq:Float, ?maxFreq:Float):Array<Float>
|
||||
public function getLevels(?startPos:Float, ?volume:Float, barCount:Int, ?levels:Array<Float>, ?ratio:Float, ?minDb:Float, ?maxDb:Float, ?minFreq:Float, ?maxFreq:Float):Array<Float>
|
||||
return inline getLevelsFromFrequencies(__frequencies = getFrequencies(startPos, volume, __frequencies), buffer.sampleRate, barCount, levels, ratio, minDb, maxDb, minFreq, maxFreq);
|
||||
|
||||
/**
|
||||
@@ -334,8 +333,8 @@ final class AudioAnalyzer {
|
||||
* @param frequencies The output for getting the frequencies, to avoid memory leaks (Optional).
|
||||
* @return Output of frequencies.
|
||||
*/
|
||||
public function getFrequencies(startPos:Float, ?volume:Float, ?frequencies:Array<Float>):Array<Float>
|
||||
return inline getFrequenciesFromSamples(__freqSamples = getSamples(startPos, fftN, true, -1, volume, __freqSamples), fftN, useWindowingFFT, frequencies);
|
||||
public function getFrequencies(?startPos:Float, ?volume:Float, ?frequencies:Array<Float>):Array<Float>
|
||||
return inline getFrequenciesFromSamples(__freqSamples = getSamples(startPos != null ? startPos : sound.time, fftN, true, -1, volume, __freqSamples), fftN, useWindowingFFT, frequencies);
|
||||
|
||||
/**
|
||||
* Analyzes an attached FlxSound from startPos to endPos in milliseconds to get the amplitudes.
|
||||
@@ -467,36 +466,37 @@ final class AudioAnalyzer {
|
||||
@:privateAccess return sound._source != null && sound._source.__backend != null && sound._source.__backend.playing;
|
||||
|
||||
inline function __readStream(startPos:Float, endPos:Float, callback:AudioAnalyzerCallback):Float @:privateAccess {
|
||||
var backend = sound._source.__backend;
|
||||
var i = backend.bufferSizes.length - backend.queuedBuffers;
|
||||
var time = backend.bufferTimes[i] * 1000;
|
||||
final backend = sound._source.__backend;
|
||||
|
||||
// TODO: Wrap it with try until i figured it out an effective way to do this...
|
||||
// So... sometimes it just uses the decoder even if it looks good?? please help
|
||||
var n = Math.floor((endPos - startPos) * __toBits);
|
||||
if (startPos >= time && startPos < backend.bufferTimes[backend.bufferSizes.length - 1] * 1000) {
|
||||
var pos = Math.floor((startPos - time) * __toBits), buf = backend.bufferDatas[i].buffer, size = backend.bufferSizes[i], c = 0;
|
||||
var i = backend.bufferLengths.length - backend.queuedBuffers - 1, time:Float;
|
||||
while (++i < backend.bufferLengths.length) if (startPos >= (time = backend.bufferTimes[i] * 1000)) {
|
||||
var pos = Math.floor((startPos - time) * __toBits), buf = backend.bufferDatas[i].buffer, size = backend.bufferLengths[i], c = 0;
|
||||
while (pos >= size) {
|
||||
if (++i >= backend.bufferSizes.length) {
|
||||
n = 0;
|
||||
break;
|
||||
}
|
||||
if (++i >= backend.bufferLengths.length) break;
|
||||
pos -= size;
|
||||
buf = backend.bufferDatas[i].buffer;
|
||||
size = backend.bufferSizes[i];
|
||||
size = backend.bufferLengths[i];
|
||||
}
|
||||
pos -= pos % __sampleSize;
|
||||
if (i >= backend.bufferLengths.length) break;
|
||||
if ((pos -= pos % __sampleSize) < 0) pos = 0;
|
||||
n -= pos % __sampleSize;
|
||||
|
||||
while (n > 0) {
|
||||
callback(getByte(buf, pos, __wordSize), c);
|
||||
if (++c > buffer.channels) c = 0;
|
||||
if ((pos += __wordSize) >= size) {
|
||||
if (++i >= backend.bufferSizes.length) break;
|
||||
if (++i >= backend.bufferLengths.length) break;
|
||||
pos = 0;
|
||||
buf = backend.bufferDatas[i].buffer;
|
||||
size = backend.bufferSizes[i];
|
||||
size = backend.bufferLengths[i];
|
||||
}
|
||||
n -= __wordSize;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return endPos - (n / __toBits);
|
||||
|
||||
@@ -1587,13 +1587,11 @@ class PlayState extends MusicBeatState
|
||||
var camera:FlxCamera = event.params[1] == "camHUD" ? camHUD : camGame;
|
||||
camera.zoom += event.params[0];
|
||||
case "Camera Bop":
|
||||
if (Options.camZoomOnBeat) {
|
||||
if (useCamZoomMult) {
|
||||
camZoomingMult += event.params[0];
|
||||
} else {
|
||||
FlxG.camera.zoom += event.params[0] * camZoomingStrength;
|
||||
camHUD.zoom += event.params[0] * camZoomingStrength;
|
||||
}
|
||||
if (useCamZoomMult) {
|
||||
camZoomingMult += event.params[0];
|
||||
} else {
|
||||
FlxG.camera.zoom += event.params[0] * camZoomingStrength;
|
||||
camHUD.zoom += event.params[0] * camZoomingStrength;
|
||||
}
|
||||
case "Camera Zoom":
|
||||
var cam = event.params[2] == "camHUD" ? camHUD : camGame;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,10 @@ import lime.app.Future;
|
||||
import lime.app.Promise;
|
||||
import lime.media.openal.AL;
|
||||
import lime.media.openal.ALBuffer;
|
||||
#if lime_vorbis
|
||||
import lime.media.vorbis.Vorbis;
|
||||
import lime.media.vorbis.VorbisFile;
|
||||
#end
|
||||
import lime.net.HTTPRequest;
|
||||
import lime.utils.Log;
|
||||
import lime.utils.UInt8Array;
|
||||
@@ -101,7 +104,10 @@ class AudioBuffer
|
||||
__srcHowl = null;
|
||||
#end
|
||||
#if lime_cffi
|
||||
if (__srcBuffer != null) AL.deleteBuffer(__srcBuffer);
|
||||
if (__srcBuffer != null) {
|
||||
AL.bufferData(__srcBuffer, 0, null, 0, 0);
|
||||
AL.deleteBuffer(__srcBuffer);
|
||||
}
|
||||
__srcBuffer = null;
|
||||
#end
|
||||
#if lime_vorbis
|
||||
@@ -178,11 +184,9 @@ class AudioBuffer
|
||||
|
||||
return audioBuffer;
|
||||
#elseif (lime_cffi && !macro)
|
||||
#if lime_vorbis // CNE
|
||||
if (funkin.options.Options.streamedMusic) {
|
||||
var vorbisFile = VorbisFile.fromBytes(bytes);
|
||||
if (vorbisFile != null) return fromVorbisFile(vorbisFile);
|
||||
}
|
||||
#if lime_vorbis
|
||||
var vorbisFile = VorbisFile.fromBytes(bytes);
|
||||
if (vorbisFile != null) return fromVorbisFile(vorbisFile);
|
||||
#end
|
||||
#if !cs
|
||||
var audioBuffer = new AudioBuffer();
|
||||
@@ -312,29 +316,29 @@ class AudioBuffer
|
||||
if (vorbisFile == null) return null;
|
||||
|
||||
var info = vorbisFile.info();
|
||||
if (info == null) return null;
|
||||
|
||||
var audioBuffer = new AudioBuffer();
|
||||
audioBuffer.channels = info.channels;
|
||||
audioBuffer.sampleRate = info.rate;
|
||||
audioBuffer.bitsPerSample = 16;
|
||||
|
||||
if (!vorbisFile.seekable() ||
|
||||
vorbisFile.pcmTotal() < #if lime_cffi @:privateAccess lime._internal.backend.native.NativeAudioSource.STREAM_BUFFER_SAMPLES #else 0x4000 #end)
|
||||
{
|
||||
// convert it to static if its too short or unseekable.
|
||||
final pcmTotal = vorbisFile.pcmTotal(-1);
|
||||
if (!vorbisFile.seekable() || pcmTotal < (audioBuffer.sampleRate << 2)) {
|
||||
vorbisFile.rawSeek(0);
|
||||
|
||||
var isBigEndian = lime.system.System.endianness == lime.system.Endian.BIG_ENDIAN;
|
||||
var bytes:Bytes = Bytes.alloc(Std.int(haxe.Int64.toInt(vorbisFile.pcmTotal()) * info.channels * 2));
|
||||
final isBigEndian = lime.system.System.endianness == lime.system.Endian.BIG_ENDIAN;
|
||||
final bytes = Bytes.alloc(Std.int((pcmTotal.high * 4294967296. + (pcmTotal.low >> 0)) * info.channels * (audioBuffer.bitsPerSample >> 3)));
|
||||
var total = 0, result = 0;
|
||||
do {
|
||||
total += (result = vorbisFile.read(bytes, total, 0x1000, isBigEndian, 2, true));
|
||||
} while (result > 0);
|
||||
result = vorbisFile.read(bytes, total, 0x1000, isBigEndian, 2, true);
|
||||
total += result;
|
||||
} while (result > 0 || result == Vorbis.HOLE);
|
||||
|
||||
audioBuffer.data = new UInt8Array(bytes);
|
||||
vorbisFile.clear();
|
||||
}
|
||||
else audioBuffer.__srcVorbisFile = vorbisFile;
|
||||
else
|
||||
audioBuffer.__srcVorbisFile = vorbisFile;
|
||||
|
||||
return audioBuffer;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ class AudioSource
|
||||
@:noCompletion inline private function init():Void
|
||||
{
|
||||
__backend.init();
|
||||
activeSources.push(this);
|
||||
if (!activeSources.contains(this)) activeSources.push(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -137,7 +137,6 @@ import lime.media.openal.AL;
|
||||
|
||||
#if lime
|
||||
__source.onComplete.remove(source_onComplete);
|
||||
__source.onLoop.remove(source_onLoop);
|
||||
__source.dispose();
|
||||
__source = null;
|
||||
#end
|
||||
@@ -165,14 +164,14 @@ import lime.media.openal.AL;
|
||||
#if lime_cffi
|
||||
var backend = __source.__backend, i = 0;
|
||||
if (backend.streamed) {
|
||||
size = backend.bufferSizes[i = backend.bufferSizes.length - backend.queuedBuffers];
|
||||
size = backend.bufferLengths[i = backend.bufferLengths.length - backend.queuedBuffers];
|
||||
buf = backend.bufferDatas[i].buffer;
|
||||
pos -= Math.floor(backend.bufferTimes[i] * buffer.sampleRate * buffer.channels * wordSize);
|
||||
while (pos > size) {
|
||||
if (++i >= backend.bufferSizes.length) return false;
|
||||
if (++i >= backend.bufferLengths.length) return false;
|
||||
pos -= size;
|
||||
buf = backend.bufferDatas[i].buffer;
|
||||
size = backend.bufferSizes[i];
|
||||
size = backend.bufferLengths[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -189,10 +188,10 @@ import lime.media.openal.AL;
|
||||
if (c % 2 == 0) ((b > leftMax) ? (leftMax = b) : (if ((b = -b) > leftMin) (leftMin = b)));
|
||||
else ((b > rightMax) ? (rightMax = b) : (if ((b = -b) > rightMin) (rightMin = b)));
|
||||
if ((pos += wordSize) >= size) #if lime_cffi {
|
||||
if (!backend.streamed || ++i >= backend.bufferSizes.length) break;
|
||||
if (!backend.streamed || ++i >= backend.bufferLengths.length) break;
|
||||
pos = 0;
|
||||
buf = backend.bufferDatas[i].buffer;
|
||||
size = backend.bufferSizes[i];
|
||||
size = backend.bufferLengths[i];
|
||||
}
|
||||
#else break; #end
|
||||
|
||||
@@ -222,7 +221,6 @@ import lime.media.openal.AL;
|
||||
}
|
||||
|
||||
__source.onComplete.add(source_onComplete);
|
||||
__source.onLoop.add(source_onLoop);
|
||||
__isValid = true;
|
||||
|
||||
__source.play();
|
||||
@@ -394,11 +392,6 @@ import lime.media.openal.AL;
|
||||
dispatchEvent(new Event(Event.SOUND_COMPLETE));
|
||||
}
|
||||
|
||||
@:noCompletion private function source_onLoop():Void
|
||||
{
|
||||
//dispatchEvent(new Event(Event.SOUND_LOOP));
|
||||
}
|
||||
|
||||
@:noCompletion private function get___audioSource():AudioSource return __source;
|
||||
@:noCompletion private function set___audioSource(source:AudioSource):AudioSource return __source = source;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user