Audio distortion bug

I am currently adding audio to my game and I have encountered this very odd bug that’s happening.

I have a menu system which can be controlled by arrow keys or by clicking the mouse. If you navigate to Level Select using the mouse and go back to the screen, the background audio comes back twice as loud and the more you repeat that, the louder and more distorted the audio becomes.

NOTE: This doesn’t happen with arrow navigation, only with the mouse and only when selecting Level Select.

Here are some relevant bits of my title screen code:

//Title.js
var storyMode = false;
var totalScore = 0;
class Title extends Phaser.Scene {
	constructor() {
		super("gameTitle");
	}

create() {
    storyMode = false;
    totalScore = 0;
	//background
    this.titleBg = this.add.image(0,0,"titleScreen").setOrigin(0,0);
    //sound
    this.titleBGM = this.sound.add("title_bgm");
    this.click = this.sound.add("click");
    this.select = this.sound.add("select");
    var musicConfig = {
        mute: false,
        volume: 1,
        rate: 1,
        detune: 0,
        seek: 0,
        loop: true,
        delay: 0
    }
//The sound error persists if I change the bgm not to loop
    this.titleBGM.play(musicConfig);

//menu setup
let activeText = 0;
    let textGroup = [];
    const texts = ['Story Mode', 'Level Select', '[credits]'];
//positioning text on screen
    texts.forEach((text, index) => {
        textGroup.push(new MenuText(this, config.scale.width / 2, 400 + 70 * index + 1, "pixelFont", text, 60, index).setOrigin(0.5));
    });
//arrow button navigation
    this.input.keyboard.on('keydown', event => {
        switch (event.key) {
            case 'ArrowUp':
                activeText -= 1;
                this.events.emit('CHANGE_BUTTON');
                break;
            case 'ArrowDown':
                activeText += 1;
                this.events.emit('CHANGE_BUTTON');
                break;
            case 'Enter':
                this.events.emit('SELECT');
                break;
        }
    });
//mouse click controls
    textGroup.forEach((text) => {
        text.on('pointerdown', event => {
            this.titleBGM.stop();
            this.events.emit('SELECT');
        });        
    });
    this.events.addListener('CHANGE_BUTTON', payload => {
        this.click.play();
        if (activeText < 0)
            activeText += texts.length;
        if (payload && typeof payload.setIndex !== 'undefined')
            activeText = payload.setIndex;
        textGroup.forEach(text => {
            text.setStyleActive(text.index === activeText % texts.length);
        });
    });
//selecting a menu item
    this.events.addListener('SELECT', payload => {
        this.select.play();
        this.titleBGM.stop();
        if (activeText == 0){
            storyMode = true;
            console.log("Title to lvl1 instructions");
            this.scene.start('instructions1');
        }
        if (activeText == 1){
            console.log("Title to level select");
            this.scene.start('levelSelect');
        }
        if (activeText == 2){
            console.log("Title to credits");
            this.scene.start('credits');
        }
            activeText += texts.length;
        if (payload && typeof payload.setIndex !== 'undefined')
            activeText = payload.setIndex;
        textGroup.forEach(text => {
            text.setStyleActive(text.index === activeText % texts.length);
        });
    });
}

update() {
	
}
}
//menu text object
class MenuText extends Phaser.GameObjects.BitmapText {
    constructor(scene, x, y, font, text, size, index) {
        super(scene, x, y, font, text, size, 0);
        this.index = index;
        this.normalTint = 0xffffff;
        this.activeTint= 0xffb700;
        this.isActive = false;
        scene.add.existing(this);
        this.setTint(this.normalTint)
            .setInteractive()
            .on('pointerover', () => scene.events.emit('CHANGE_BUTTON', { setIndex: index }));
        this.setStyleActive(index === 0);
    }
    setStyleActive(active) {
        if (this.isActive === active)
            return;
        this.isActive = active;
        this.setTint(this.isActive ? this.activeTint : this.normalTint);
    }
}


Here is my level select screen code (it has some code which is very similar to the title screen when it comes to navigation, I’m not sure if that’s causing the issue)

//LevelSelect.js
class LevelSelect extends Phaser.Scene {
	constructor() {
		super("levelSelect");
	}

create() {
	//background
    this.levelSelectBg = this.add.image(0,0,"level_select_bg").setOrigin(0,0);
    //level icons
    
	//menu options
	let activeText = 0;
    let textGroup = [];
    let iconGroup = [];
    const texts = ['Level 1', 'Level 2', 'Level 3'];
    const icons = [0,1,2];
    icons.forEach((icon, index) => {
        iconGroup.push(new Icon(this, 300 + 210 * index + 1, 300,  "level_icon", index).setOrigin(0.5));
    });
    texts.forEach((text, index) => {
        textGroup.push(new MenuText(this, 300 + 210 * index + 1, 420,  "pixelFont", text, 60, index).setOrigin(0.5));
    });
    textGroup.push(new MenuText(this, config.scale.width/2, 550, "pixelFont", "[back]", 60, 3).setOrigin(0.5));
    this.input.keyboard.on('keydown', event => {
        switch (event.key) {
            case 'ArrowLeft':
                activeText -= 1;
                this.events.emit('CHANGE_BUTTON');
                break;
            case 'ArrowRight':
                activeText += 1;
                this.events.emit('CHANGE_BUTTON');
                break;
            case 'ArrowDown':
                    activeText = 3;
                    this.events.emit('CHANGE_BUTTON');
                break;
            case 'ArrowUp':
                activeText = 1;
                this.events.emit('CHANGE_BUTTON');
                break;
            case 'Enter':
                this.events.emit('SELECTITEM');
                break;
        }
    });
    textGroup.forEach((text) => {
        text.on('pointerdown', event => {
            this.events.emit('SELECTITEM');
        });        
    });
    this.events.addListener('CHANGE_BUTTON', payload => {
        if (activeText < 0)
            activeText += textGroup.length;
        if (payload && typeof payload.setIndex !== 'undefined')
            activeText = payload.setIndex;
        textGroup.forEach(text => {
            text.setStyleActive(text.index === activeText % textGroup.length);
        });
    });
    this.events.addListener('SELECTITEM', payload => {
        if (activeText == 0){
            console.log("Level Select to lvl1 instructions");
            this.scene.start('instructions1');
        }
        if (activeText == 1){
            console.log("Level Select to lvl2 instructions");
            this.scene.start('instructions2');
        }
        if (activeText == 2){
            console.log("Level Select to lvl3 instructions");
            this.scene.start('gameTitle');
        }
        if (activeText == 3){
            console.log("Level Select to title");
            this.scene.start('gameTitle');
        }
            activeText += texts.length;
        if (payload && typeof payload.setIndex !== 'undefined')
            activeText = payload.setIndex;
        textGroup.forEach(text => {
            text.setStyleActive(text.index === activeText % texts.length);
        });
    });
}
update() {
}
}

One option is to completely disable mouse navigation, but that would really limit functionality/ease of access, considering I’m developing this game for a younger audience. Any help would be greatly appreciated :slight_smile: