Using THREE.AudioAnalyser to manipulate user-defined file

I am having some issues when trying to use THREE.AudioAnalyser to manipulate the data I get from the audio being played.

I’ll post the relevant code below:

function loadAudio(){

    input = document.getElementById("audioInput");    //id for an input type="file"
    audioControls = document.getElementById("audioControls");    //id for my audio controls

    input.onchange = function() {

        var reader = new FileReader();

        var file = input.files[0];

        reader.readAsArrayBuffer( file );

        audioControls.src = URL.createObjectURL(file);

        reader.addEventListener('load', function (event){

            var buffer = event.target.result;

            var context = THREE.AudioContext.getContext();

            context.decodeAudioData(buffer, function(audioBuffer){

                listener = new THREE.AudioListener();

                camera.add(listener);

                sound = new THREE.Audio(listener);

                sound.setBuffer(audioBuffer);

                sound.setLoop(true);

                sound.setVolume(0.5);

                analyser = new THREE.AudioAnalyser(sound, 32);

            } );

        } );

    }

My audio controls can play and pause an audio file loaded by the user, so that part works as intended. However, I think there is an issue that I do not connect the variable “sound” to what is currently being played, and therefore I can not get any audio information out of “sound”. I’ve tried simply connecting an AudioAnalyser to the variable “file” but it does not seem to work, and I cannot find any working alternatives to setting the source to my audio controls (audioControls.src).

Does anyone have an idea how I can solve this?

Your code looks fine. Do you mind demonstrating the issue with a live example? You can also try to modify the official audio visualizer to show the problem.

I added the code to a JSFiddle -> https://jsfiddle.net/rvn70gco/1/

I am currently trying to just get the AudioAnalyser to work as intended, but it keeps printing out 0 as the average frequency (See line 95-99 in the .js-code). I think the optimal thing would be to simply re-do the way that I set the source of the audio controls (line 50), since I am currently playing an audio file through it, but then try to get the audio information from the variable “sound” (line 63-69).

However, I can’t seem to figure out how I can do this is an easy manner, I managed to get it to work by instantly playing the sound, but I do not want the audio file to play before the user has pressed the button to make it play.

Try it like so: https://jsfiddle.net/zpkL1trv/

You have to ensure to call play() on the audio object so the audio is actually played via Web Audio. Right now, you just use the HTML element which means Web Audio is not involved at all. It would only work if you connect the HTML audio element with Web Audio like in the official example (meaning by using Audio.setMediaElementSource()).

Notice that the audio is automatically played when the decode has finished. You might want to introduce a custom button that starts the playback.

2 Likes

I’ve gotten it to work previously by calling play() on the audio object, like you just did. However, it will make the audio file play as soon as it’s loaded, which is not what I’m after unfortunately.

I have managed to get it closer to working as intended, by adding event listeners to the play and pause function of the controls as follows:

audioControls.addEventListener(“play”, function(){
sound.play();
})

This seems to do part of the trick, however I’m not sure how to go about getting the actual timer to work then (showing the current time and the total time of the song that is playing).

I tried using setMediaElementSource() to connect the audio element to the audio player, but with no luck unfortunately. Is there any chance you could have a look and see if you could get it working Mugen87? :slight_smile:

Updated fiddle with Audio.setMediaElementSource(): https://jsfiddle.net/4q3p6u5v/

1 Like

Awesome, seems I misunderstood setMediaElementSource and tried using it “the other way around”, if that makes sense. That works exactly like I want it too, plus it’s less code so that’s always nice!

Thanks a bunch, Mugen87!

1 Like