fix sound destruction
This commit is contained in:
@@ -1,48 +1,45 @@
|
|||||||
var soloud = use('soloud')
|
var soloud = use('soloud')
|
||||||
var tween = use('tween')
|
var tween = use('tween')
|
||||||
var io = use('io')
|
var io = use('io')
|
||||||
var res = use('resources')
|
var res = use('resources')
|
||||||
var doc = use('doc')
|
var doc = use('doc')
|
||||||
|
|
||||||
soloud.init();
|
soloud.init()
|
||||||
|
|
||||||
var audio = {};
|
var audio = {}
|
||||||
audio[doc.sym] = `Audio docs.`
|
var pcms = {}
|
||||||
|
|
||||||
var pcms = {};
|
// keep every live voice here so GC can’t collect it prematurely
|
||||||
|
var voices = []
|
||||||
|
|
||||||
audio.pcm = function pcm(file)
|
// load-and-cache WAVs
|
||||||
{
|
audio.pcm = function pcm(file) {
|
||||||
file = res.find_sound(file);
|
file = res.find_sound(file); if (!file) return
|
||||||
if (!file) return//throw new Error(`Could not findfile ${file}`);
|
if (pcms[file]) return pcms[file]
|
||||||
if (pcms[file]) return pcms[file];
|
var buf = io.slurpbytes(file)
|
||||||
var bytes = io.slurpbytes(file)
|
return pcms[file] = soloud.load_wav_mem(buf)
|
||||||
var newpcm = soloud.load_wav_mem(io.slurpbytes(file));
|
|
||||||
pcms[file] = newpcm;
|
|
||||||
return newpcm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
voices = voices.filter(v => v.is_valid())
|
||||||
|
}
|
||||||
|
|
||||||
|
// play a one‑shot; returns the voice for volume/stop control
|
||||||
audio.play = function play(file) {
|
audio.play = function play(file) {
|
||||||
var pcm = audio.pcm(file);
|
var pcm = audio.pcm(file); if (!pcm) return
|
||||||
if (!pcm) return;
|
var voice = soloud.play(pcm)
|
||||||
return soloud.play(pcm);
|
voices.push(voice)
|
||||||
};
|
return voice
|
||||||
audio.play[doc.sym] = `Given a file path, plays a sound. Returns a sound object.`
|
}
|
||||||
|
|
||||||
|
// cry is just a play+stop closure
|
||||||
audio.cry = function cry(file) {
|
audio.cry = function cry(file) {
|
||||||
var voice = audio.play(file);
|
var v = audio.play(file); if (!v) return
|
||||||
if (!voice) return;
|
return function() { v.stop(); v = null }
|
||||||
return function() {
|
}
|
||||||
voice.stop();
|
|
||||||
voice = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
audio.cry[doc.sym] =
|
|
||||||
`Given a file path, plays a sound. Invoke the returned object to stop it.`
|
|
||||||
|
|
||||||
var song;
|
// music with optional cross‑fade
|
||||||
|
var song
|
||||||
// Play 'file' for new song, cross fade for seconds
|
|
||||||
audio.music = function music(file, fade = 0.5) {
|
audio.music = function music(file, fade = 0.5) {
|
||||||
if (!file) {
|
if (!file) {
|
||||||
if (song) song.volume = 0;
|
if (song) song.volume = 0;
|
||||||
@@ -71,33 +68,30 @@ audio.music = function music(file, fade = 0.5) {
|
|||||||
// tween.tween(temp2, 'volume', 0, fade);
|
// tween.tween(temp2, 'volume', 0, fade);
|
||||||
song = temp;
|
song = temp;
|
||||||
song.loop = true;
|
song.loop = true;
|
||||||
|
temp2.stop()
|
||||||
};
|
};
|
||||||
audio.music[doc.sym] = `Play the given music file, with an optional cross fade. The song will loop. When this is invoked again, the previous music is replaced.`
|
|
||||||
|
|
||||||
var ss = use('sdl_audio')
|
|
||||||
|
|
||||||
var feeder = ss.open_stream("playback")
|
|
||||||
|
|
||||||
feeder.set_format({format:"f32", channels:2,samplerate:44100})
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// pump + periodic cleanup
|
||||||
|
//
|
||||||
|
var ss = use('sdl_audio')
|
||||||
|
var feeder = ss.open_stream("playback")
|
||||||
|
feeder.set_format({format:"f32", channels:2, samplerate:44100})
|
||||||
feeder.resume()
|
feeder.resume()
|
||||||
|
|
||||||
var FRAMES = 1024
|
var FRAMES = 1024
|
||||||
var CHANNELS = 2
|
var CHANNELS = 2
|
||||||
var BYTES_PER_F = 4
|
var BYTES_PER_F = 4
|
||||||
var SAMPLES = FRAMES * CHANNELS
|
var CHUNK_BYTES = FRAMES * CHANNELS * BYTES_PER_F
|
||||||
var CHUNK_BYTES = FRAMES * CHANNELS * BYTES_PER_F
|
|
||||||
|
|
||||||
function pump()
|
function pump() {
|
||||||
{
|
|
||||||
if (feeder.queued() < CHUNK_BYTES*3) {
|
if (feeder.queued() < CHUNK_BYTES*3) {
|
||||||
var mm = soloud.mix(FRAMES)
|
feeder.put(soloud.mix(FRAMES))
|
||||||
feeder.put(mm)
|
cleanup()
|
||||||
}
|
}
|
||||||
|
|
||||||
$_.delay(pump, 1/240)
|
$_.delay(pump, 1/240)
|
||||||
}
|
}
|
||||||
|
|
||||||
//pump()
|
pump()
|
||||||
|
|
||||||
return audio;
|
return audio
|
||||||
|
|||||||
@@ -177,6 +177,12 @@ static JSValue js_voice_setInaudibleBehavior(JSContext *js, JSValueConst self, i
|
|||||||
return JS_NULL;
|
return JS_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSValue js_voice_valid(JSContext *js, JSValueConst self, int argc, JSValue *argv)
|
||||||
|
{
|
||||||
|
unsigned int voice = *js2voice(js, self);
|
||||||
|
return JS_NewBool(js, Soloud_isValidVoiceHandle(soloud, voice));
|
||||||
|
}
|
||||||
|
|
||||||
SOLOUD_GETSET(Volume, number);
|
SOLOUD_GETSET(Volume, number);
|
||||||
SOLOUD_GETSET(Pan, number)
|
SOLOUD_GETSET(Pan, number)
|
||||||
SOLOUD_GETSET(Samplerate, number)
|
SOLOUD_GETSET(Samplerate, number)
|
||||||
@@ -197,6 +203,7 @@ static const JSCFunctionListEntry js_voice_funcs[] = {
|
|||||||
JS_CGETSET_DEF("loop", js_voice_get_Looping, js_voice_set_Looping),
|
JS_CGETSET_DEF("loop", js_voice_get_Looping, js_voice_set_Looping),
|
||||||
JS_CGETSET_DEF("autoStop", js_voice_get_AutoStop, js_voice_set_AutoStop),
|
JS_CGETSET_DEF("autoStop", js_voice_get_AutoStop, js_voice_set_AutoStop),
|
||||||
JS_CGETSET_DEF("protect", js_voice_get_ProtectVoice, js_voice_set_ProtectVoice),
|
JS_CGETSET_DEF("protect", js_voice_get_ProtectVoice, js_voice_set_ProtectVoice),
|
||||||
|
JS_CFUNC_DEF("is_valid", 0, js_voice_valid),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const JSCFunctionListEntry *js_Bus_funcs;
|
static const JSCFunctionListEntry *js_Bus_funcs;
|
||||||
|
|||||||
Reference in New Issue
Block a user