Open Farkal opened 6 years ago
Is there any disadvantages to create the instance over and over again for you?
Yes on chrome on mobile it doesn't work, the events are not linked to the new instance and refuse to play the music.
I create a function for the Howl object and it work, chrome stop annoying me and i am able to load my musics easily :
changeSrc: function(newSrc) {
var self = this;
self.stop();
self._src = newSrc;
let sounds = self._sounds;
self._sprite = {};
self._duration = 0;
sounds[0]._node.src = newSrc;
self.load();
},
@Farkal Where did you add this function, and how do you call it?
Got it! Added it to the howler.js file as part of the Howl.prototype
object.
I find a new way to implement this:
changeSrc: function (newSrc) {
let self = this;
self.unload();
self._src = newSrc;
self.load();
}
@Farkal @jasongrishkoff im working in a sampler project and i need to update the src from the url in a json file, is there any way to do that??, any idea?
@Farkal @jasongrishkoff im working in a sampler project and i need to update the src from the url in a json file, is there any way to do that??, any idea?
You can write an helper parse source urls from json file and push to another array. After that you can play audios from array on howlerjs onload event.
I find a new way to implement this:
changeSrc: function (newSrc) { let self = this; self.unload(); self._src = newSrc; self.load(); }
Really good solution rather than old one. But there are two point important if anyone use these solutions.
-First solution does not clear cache and some cases this is good. But somehome (I did not have a time to debug) onend event fired more than one.
-Second solution works clear. But if you need to use cache you should do some modification on unload method like that:
Change method signature like that:
unload: function(dontRemoveCache)
Get into the if condition this lines in the unload method:
// Delete this sound from the cache (if no other Howl is using it).
if(!dontRemoveCache) {
var remCache = true;
for (i = 0; i < Howler._howls.length; i++) {
if (Howler._howls[i]._src === self._src) {
remCache = false;
break;
}
}
if (cache && remCache) {
delete cache[self._src];
}
}
Lastly use this changeSrc method instead of above:
changeSrc: function (newSrc) {
var self = this;
self.unload(true);
self._src = newSrc;
self.load();
}
Get into the if condition this lines in the unload method:
// Delete this sound from the cache (if no other Howl is using it). if(!dontRemoveCache) { var remCache = true; for (i = 0; i < Howler._howls.length; i++) { if (Howler._howls[i]._src === self._src) { remCache = false; break; } } if (cache && remCache) { delete cache[self._src]; } }
Lastly use this changeSrc method instead of above:
changeSrc: function (newSrc) { var self = this; self.unload(true); self._src = newSrc; self.load(); }
This worked for me. Just copying the edited code from version 2.1.2 to make it easier to edit (it's the second unload function):
unload: function (dontRemoveCache) {
var self = this;
// Stop playing any active sounds.
var sounds = self._sounds;
for (var i = 0; i < sounds.length; i++) {
// Stop the sound if it is currently playing.
if (!sounds[i]._paused) {
self.stop(sounds[i]._id);
}
// Remove the source or disconnect.
if (!self._webAudio) {
// Set the source to 0-second silence to stop any downloading (except in IE).
self._clearSound(sounds[i]._node);
// Remove any event listeners.
sounds[i]._node.removeEventListener('error', sounds[i]._errorFn, false);
sounds[i]._node.removeEventListener(Howler._canPlayEvent, sounds[i]._loadFn, false);
// Release the Audio object back to the pool.
Howler._releaseHtml5Audio(sounds[i]._node);
}
// Empty out all of the nodes.
delete sounds[i]._node;
// Make sure all timers are cleared out.
self._clearTimer(sounds[i]._id);
}
// Remove the references in the global Howler object.
var index = Howler._howls.indexOf(self);
if (index >= 0) {
Howler._howls.splice(index, 1);
}
// Delete this sound from the cache (if no other Howl is using it).
if (!dontRemoveCache) {
var remCache = true;
for (i = 0; i < Howler._howls.length; i++) {
if (Howler._howls[i]._src === self._src || self._src.indexOf(Howler._howls[i]._src) >= 0) {
remCache = false;
break;
}
}
if (cache && remCache) {
delete cache[self._src];
}
}
// Clear global errors.
Howler.noAudio = false;
// Clear out `self`.
self._state = 'unloaded';
self._sounds = [];
self = null;
return null;
},
import { Howl } from 'howler';
let audioPlayer = null;
Howl.prototype.changeSong = function(o) {
var self = this;
self.unload();
self._duration = 0; // init duration
self._sprite = {};// init sprite
self._src = typeof o.src !== 'string' ? o.src : [o.src];
self._format = typeof o.format !== 'string' ? o.format : [o.format];
self.load(); // => update duration, sprite(var timeout)
};
function generateHowlerAudio(song) {
if (audioPlayer == null) {
audioPlayer = new Howl({
src: song.src,
format: song.format,
preload: true,
autoplay: false,
loop: false,
volume: 1
});
} else {
audioPlayer.changeSong(song);
}
}
Faced this issue in Safari. Turns out I wasn't unloading the Audio player.
export default function useHowler(options: HowlerOptions) {
const player = useRef();
useEffect(() => {
player.current = new Howl(options);
// Unload the Audio player during unmount --cleanup
return () => {
player.current && player.current.unload();
}
}, []);
return { play: ..., stop: ..., fade: ... }
}
I explain my problem : I have a website with a lot of musics and i need to allow my users to listen to this musics, but there is so much musics that I can't use an array and define it at the beginning. So is there any solution ? Right now I have to create a new Howler instance, set the events, the volume etc... each time an user want to play a track. At least it should be possible to just change the src and not recreate all the instance of the object no ?