This is my first time working with React Native together with Expo and I have been learning a lot, but this is something I am still unable to fix.
I am using expo-av and for short sounds I am not having any problem. They play and then I call unloadAsync()
and no issues there. But when it comes to the background music, I am stopping, unloadind, making sure the useEffect is returning but for some reason even after the game is over and I am sent to the game over or victory screen, the music keeps playing and if for some reason I try to start another game, it will be one audio on top of the other.
Inside the class responsible for seting up playback:
class AudioController {
constructor() {
this.bgMusic = new Audio.Sound()
this.flipSound = new Audio.Sound()
this.matchSound = new Audio.Sound()
this.victorySound = new Audio.Sound()
this.gameOverSound = new Audio.Sound()
}
loadAndPlay = async (audioObject, audioFile, loop = false, volume = 1.0) => {
try {
await audioObject.loadAsync(audioFile);
audioObject.setIsLoopingAsync(loop);
audioObject.setVolumeAsync(volume);
await audioObject
.playAsync()
.then(async playbackStatus => {
if (!loop) {
setTimeout(() => {
audioObject.unloadAsync()
}, playbackStatus.playableDurationMillis)
}
})
.catch(error => {
console.log(error)
})
} catch (error) {
console.log(error);
}
}
playBgMusic = async () => {
await this.loadAndPlay(this.bgMusic, bgMusic, true, 0.5); // Loop and set the volume to 50%
}
stopBgMusic = async () => {
try {
await this.bgMusic.stopAsync();
await this.bgMusic.unloadAsync();
} catch (error) {
console.log(error);
}
}
playFlipSound = async () => {
await this.loadAndPlay(this.flipSound, flipSound);
}
playMatchSound = async () => {
await this.loadAndPlay(this.matchSound, matchSound);
}
playVictorySound = async () => {
await this.loadAndPlay(this.victorySound, victorySound);
}
playGameOverSound = async () => {
await this.loadAndPlay(this.gameOverSound, gameOverSound);
}
}
export default AudioController``
Inside the component where I want to use it.
`useEffect(() => {
audioController.playBgMusic()
resetTurn()
setTimer(level)
shuffleCards()
return () => {
console.log(' Start game cleanup executed')
audioController.stopBgMusic()
}
}, []);`
Of course I am properly instancing the audioController (or the other sounds would not be working) and I am triggering the game over and victory functions. So the problem is either with the way I am trying to stop the music or the component is not unmounting. I have also tried to stop the music inside the fuction that handles the game over right before it sends me to a different screen and still the same. Also tried using React Context and the result is the same, the music will not stop and new instances will start if I try to start a new game.