Can't get my audio to work after update to 4.0

#1

Hello,

After I updated to BabylonJS 4.0, I get this error:

babylon.js:16 Uncaught (in promise) TypeError: Cannot read property 'canUseWebAudio' of undefined

When this line is reached in my code:

this.pickUpSound = new BABYLON.Sound('Letter.PickUp', './assets/sounds/letter_collection_2notes.wav', this.scene);

I thought it was because BabylonJS 4.0 was enforcing the audioContext policy of waiting for a button press of the user to resume the audio, as explained here: Autoplay Policy Changes  |  Web  |  Google Developers

Hence I added these lines to my code:

this.startButton.onPointerDownObservable.add(e=> {
            let audioContext = new AudioContext();
            audioContext.resume().then(
                () => {
                    console.log('Playback resumed successfully');
            });            
        });

But that does not solve the problem…
Any idea?

#2

Ok, I don’t understand anything anymore. I reverted to BabylonJS 4.0.0-alpha.4 and reverted my changes (by checking out to the previous commit) and the problem is still there :confused:
How is that possible?

It seems that no AudioEngine is initialised… when I stopped the execution just before I load my sounds, and I check the variable BABYLON.Engine.audioEngine, it is undefined.

When I stopped the execution at the same line on my online backup of the game, I get a well-defined BABYLON.Engine.audioEngine

EDIT: I made it work again, with 4.0.0-alpha.4! I needed to delete node_modules and re-run npm install. Somehow npm did not revert babylonjs correctly. The question remains: how to make my sounds work with the real 4.0?

#3

Can you create a playground with this issue? That will help us debug the issue.

#4

Probably an issue with modules as the audio works in the playground
Can you make sure that Audio is imported?

#5

What Audio? how do I check that?

#6

How do you use Babylon.js? through es6 import?

#7

I installed it through npm, I run my local server with webpack, and I use typescript, with the settings:

{
  "compilerOptions": {
    /* Basic Options */
    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "lib": ["es2015", "dom"],                             /* Specify library files to be included in the compilation. */
    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */
    /* List of folders to include type definitions from. */
    "types": [
      "babylonjs",
      "babylonjs-materials",
      "babylonjs-gui"
    ],                           /* Type declaration files to be included in compilation. */
    "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
  }
}

@bghgary to be honest, I think that the line:

this.pickUpSound = new BABYLON.Sound('Letter.PickUp', './assets/sounds/letter_collection_2notes.wav', this.scene);

would work in the PG, right? it seems that my problem is that the BABYLON.Engine.audioEngine is undefined at the time I reach this line; not sure how I could reproduce that…

#8

Ok so I started a project from scratch installing the last version of babylonjs (stable) and of webpack. I wrote the bare minimum:

import * as BABYLON from 'babylonjs';

export class Main { // that is kind of our Game State Manager 

    private _canvas: HTMLCanvasElement;
    private _engine!: BABYLON.Engine;
    scene !: BABYLON.Scene;

    constructor(canvasElement : string) {
        // Create canvas and engine.
        this._canvas = document.getElementById(canvasElement) as HTMLCanvasElement;           
        this._engine = new BABYLON.Engine(this._canvas, true);
        this.createScene(this._engine, this._canvas);    
        this.initScene();
    }

    createScene(engine:BABYLON.Engine, canvas:HTMLCanvasElement){
        
        this.scene = new BABYLON.Scene(engine);

        // This creates and positions a free camera (non-mesh)
        var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), this.scene);

        var music1 = new BABYLON.Sound("Violons11", "./assets/sounds/congratulation-small.wav", this.scene, 
		soundReady, { loop: true });
        
        function soundReady() {
            music1.play();
        }

    }

    protected initScene() {
                
        // Register update function:
        this.scene.registerBeforeRender(() => this.update())
        
        // Run the render loop.
        this._engine.runRenderLoop(() => {
            this.scene.render();
        });
        
        // The canvas/window resize event handler.
        window.addEventListener('resize', () => {
            this._engine.resize();
        });
    }

    update(){}

      
}

window.addEventListener('DOMContentLoaded', () => {
    // Create the game using the 'renderCanvas'.
    let game = new Main('renderCanvas');  

});

And it worked …
So I have no idea what is going on in my other project :smiley: :frowning: :disappointed_relieved::sob:

I will post the solution if I can find it…

2 Likes
#9

Ok, so I deleted again my node_modules folder, I deleted the package I did not need anymore from the package.json and this time I ran:

npm update
npm update -D

And now the game is working again:


You can also see that the new inspector is magically working too! (I couldn’t get it to work for some reason).

So there is definitely something off with npm…

#10

haha cool! Glad that is work :smiley: