Closed FlorianBT closed 8 years ago
Looks like this is a bug in howler. Can you log this in https://github.com/goldfire/howler.js repo.
Sure! Do I present this issue linked to the use of haxe-howler? I'll do some more testing directly in JS to be sure though. I don't know if the type cast is done on Have or JS side
Le jeu. 8 oct. 2015 13:57, Adi notifications@github.com a écrit :
Looks like this is a bug in howler. Can you log this in https://github.com/goldfire/howler.js repo.
— Reply to this email directly or view it on GitHub https://github.com/adireddy/haxe-howler/issues/3#issuecomment-146516342.
May be if you look in the generated javascript file, you can find how the parameters are casted.
Post the js file here if you can.
The generated JS file is more than 2MB big in debug (HTML5 game). I would rather not post the whole file here, especially as it is for a client. Which bits interest you the most? The actual calls to howler? Or the js_Boot parts where the JS magic seems to happen?
howler calls may help
SoundMng is the base class for playing sound. It just takes a Howl instance and plays it with some tweaking parameters. It can also load a sound directly from path. Nothing magical in here, just fyi as it is the base class dealing with Howler.
$hxClasses["casuHaxeFlxEngine.SoundMng"] = casuHaxeFlxEngine_SoundMng;
casuHaxeFlxEngine_SoundMng.__name__ = ["casuHaxeFlxEngine","SoundMng"];
casuHaxeFlxEngine_SoundMng.__properties__ = {get_instance:"get_instance"}
casuHaxeFlxEngine_SoundMng.instance = null;
casuHaxeFlxEngine_SoundMng.get_instance = function() {
return casuHaxeFlxEngine_SoundMng.instance;
};
casuHaxeFlxEngine_SoundMng.prototype = {
load: function(Path,Volume,Looping) {
var audio = null;
if(Path != null && Path.length > 0) {
var options = { };
options.autoplay = false;
options.preload = true;
options.pool = 2;
options.loop = Looping;
options.volume = Volume;
options.src = [Path + ".ogg",Path + ".m4a",Path + ".mp3",Path + ".ac3"];
options.onend = function(id) {
if(!audio.loop(id)) audio.stop(id);
};
options.onfaded = function(id1) {
if(audio.volume(id1) <= 0) audio.stop(id1);
};
audio = new Howl(options);
}
return audio;
}
,play: function(Sound,AudioID,Volume,Looping) {
if(Sound != null && js_Boot.__instanceof(Sound,Howl)) {
var soundId = Sound.play(AudioID);
Sound.volume(Volume,soundId);
Sound.loop(Looping,soundId);
return soundId;
}
return null;
}
,stop: function(Sound,AudioID,Fade,FadeDuration) {
if(Sound != null && js_Boot.__instanceof(Sound,Howl)) {
if(Fade && Sound.playing(AudioID)) Sound.fade(Sound.volume(AudioID),0,FadeDuration,AudioID); else Sound.stop(AudioID);
}
}
,playSound: function(Sound,AudioID,Volume,Looping) {
if(Looping == null) Looping = false;
if(Volume == null) Volume = 1.0;
var sound;
if(js_Boot.__instanceof(Sound,Howl)) sound = Sound; else sound = this.load(Sound,Volume,Looping);
var id = this.play(sound,AudioID,Volume,Looping);
if(sound != Sound) return sound; else return id;
}
,stopSound: function(Sound,AudioID,Fade,FadeDuration) {
if(FadeDuration == null) FadeDuration = 500;
if(Fade == null) Fade = true;
this.stop(Sound,AudioID,Fade,FadeDuration);
}
,__class__: casuHaxeFlxEngine_SoundMng
};
SoundManagerONI is child of SoundMng. This one is the interesting part, as it loads all the sound sprites and play them. I use enum values or string values to determine which sound to play. This part works quite well, I have no issues with it, I always retrieve the correct Howl instance for my needs.
$hxClasses["onisep.SoundManagerONI"] = onisep_SoundManagerONI;
onisep_SoundManagerONI.__name__ = ["onisep","SoundManagerONI"];
onisep_SoundManagerONI.get_instance = function() {
if(casuHaxeFlxEngine_SoundMng.get_instance() == null) return new onisep_SoundManagerONI(); else return casuHaxeFlxEngine_SoundMng.get_instance();
};
onisep_SoundManagerONI.__super__ = casuHaxeFlxEngine_SoundMng;
onisep_SoundManagerONI.prototype = $extend(casuHaxeFlxEngine_SoundMng.prototype,{
_soundSprites: null
,_preloadCallback: null
,_preloadCount: null
,_preloadTotal: null
,loadSoundSprite: function(Path,Volume,Looping) {
if(Looping == null) Looping = false;
if(Volume == null) Volume = 1.0;
this._preloadTotal++;
haxe_Log.trace("loading " + Path,{ fileName : "SoundManagerONI.hx", lineNumber : 83, className : "onisep.SoundManagerONI", methodName : "loadSoundSprite"});
var audio = null;
if(Path != null && Path.length > 0) {
var json = JSON.parse(openfl_Assets.getText(Path + ".json"));
var options = { };
options.autoplay = false;
options.preload = true;
options.pool = 2;
options.loop = Looping;
options.volume = Volume;
options.src = [Path + ".ogg",Path + ".m4a",Path + ".mp3",Path + ".ac3"];
options.sprite = json.sprite;
options.onend = function(id) {
if(!audio.loop(id)) audio.stop(id);
};
options.onfaded = function(id1) {
if(audio.volume(id1) <= 0) audio.stop(id1);
};
options.onload = $bind(this,this.onSoundLoaded);
options.onloaderror = $bind(this,this.onSoundLoaded);
audio = new Howl(options);
}
return audio;
}
,playSound: function(Type,AudioID,Volume,Looping) {
if(Looping == null) Looping = false;
if(Volume == null) Volume = 1.0;
var audio;
var key = this.determineType(Type);
audio = this._soundSprites.get(key);
if(audio == null) return null;
return this.play(audio,this.getSoundId(AudioID),Volume,Looping);
}
,stopSound: function(Type,AudioID,Fade,FadeDuration) {
if(FadeDuration == null) FadeDuration = 500;
if(Fade == null) Fade = true;
var audio;
var key = this.determineType(Type);
audio = this._soundSprites.get(key);
if(audio == null) return;
this.stop(audio,AudioID,Fade,FadeDuration);
}
,getSoundId: function(Name) {
var id = null;
switch(Type.enumIndex(Name)) {
case 0:
id = "clickButton";
break;
case 1:
id = "click-label";
break;
case 2:
id = "goodanswer";
break;
case 3:
id = "badanswer";
break;
case 4:
id = "success_small";
break;
case 5:
id = "landing";
break;
case 6:
id = "unlock";
break;
case 7:
id = "open-popup";
break;
case 8:
id = "fiche-perso";
break;
case 9:
id = "object-found";
break;
case 10:
id = "object-inventory";
break;
case 11:
id = "glory";
break;
default:
return Name;
}
return id;
}
,determineType: function(T) {
if(T != null) {
if(js_Boot.__instanceof(T,onisep_SoundType)) return T; else if(typeof(T) == "string") return Type.createEnum(onisep_SoundType,T);
}
return null;
}
,setPreloadCallback: function(Callback) {
this._preloadCallback = Callback;
}
,onSoundLoaded: function() {
this._preloadCount++;
if(this._preloadCallback != null) this._preloadCallback(this._preloadCount / this._preloadTotal);
}
,__class__: onisep_SoundManagerONI
});
The issue I found is located here, in an event callback (onend
callback)
var audio = null;
if(Path != null && Path.length > 0) {
var json = JSON.parse(openfl_Assets.getText(Path + ".json"));
var options = { };
options.autoplay = false;
options.preload = true;
options.pool = 2;
options.loop = Looping;
options.volume = Volume;
options.src = [Path + ".ogg",Path + ".m4a",Path + ".mp3",Path + ".ac3"];
options.sprite = json.sprite;
options.onend = function(id) {
if(!audio.loop(id)) audio.stop(id);
};
options.onfaded = function(id1) {
if(audio.volume(id1) <= 0) audio.stop(id1);
};
options.onload = $bind(this,this.onSoundLoaded);
options.onloaderror = $bind(this,this.onSoundLoaded);
audio = new Howl(options);
}
return audio;
In Howl.hx
, onend
is Int->Void
, so id
should be an Int
. Therefore audio.loop(id)
should return a boolean.
Does it help?
yes, got it now... I think I know the issue. Will do a quick test and then update the externs.
Fixed it @FlorianBT. Please check and let me know. v2.0.1 http://lib.haxe.org/p/howlerjs/2.0.1
Also updated the sample to trace the return value of loop
function call and its returning Bool
.
http://adireddy.github.io/demos/haxe-howler/
Play sound 1 or sound 2 and see the traces in console.
Hello again.
Sadly, my project doesn't compile anymore with your latest changes.
SoundManagerONI.hx:107: characters 7-28 : Cannot compare howler.Howl and Int
SoundMng.hx:86: characters 15-36 : howler.Howl should be Float
SoundMng.hx:86: characters 15-36 : For function argument 'from'
SoundMng.hx:46: characters 7-28 : Cannot compare howler.Howl and Int
Involved lines in Haxe, in order:
SoundManagerONI.hx:107: characters 7-28 : Cannot compare howler.Howl and Int
options.onfaded = function(id:Int):Void {
//trace("faded " + id + " volume : " + audio.volume(id));
===> if(audio.volume(id) <= 0)
audio.stop(id);
};
};
SoundMng.hx:86: characters 15-36 : howler.Howl should be Float
SoundMng.hx:86: characters 15-36 : For function argument 'from'
if(Fade && Sound.playing(AudioID))
{
===> Sound.fade(Sound.volume(AudioID), 0, FadeDuration, AudioID);
}
SoundMng.hx:46: characters 7-28 : Cannot compare howler.Howl and Int
options.onfaded = function(id:Int):Void {
===> if(audio.volume(id) <= 0)
audio.stop(id);
};
};
I looked a bit at your new overloads and did some researches as I couldn't find a reason it selected the wrong overload. I found this : http://blog.onthewings.net/2012/07/13/haxe-tips-advanced-method-overloading-with-macros/ Maybe we're in the same case here.
I see the problem and it's really annoying... anyway as a quick fix I changed the return type to Dynamic
to fix the issue.
Can you try again and let me know. v2.0.2
I did a quick test and it's fine.
Tested, compiling and working as expected. Thanks a lot for your time!
:+1:
I found out that Howl.loop returns a Howl object instead of a boolean value as expected
This would log the whole Howl object. In my case, this:
As you can see, the Howl instance itself is set to loop. Calling
audio.loop()
would returntrue
. But when passing a sound id, it returns the Howl instance.Tracking down what happens in the javascript code, my guess is that a type check "fails" in howler code.
Specifically this bit of code:
The id parameter of
loop()
is probably converted fromInt
toBool
as part of the optional parameters substitution.Thanks in advance for any quick fix :)