How can I use an analyzer created from the audio context to determine if an audio signal is audible?

First I describe my problem, I create an automated playlist from random songs, some songs contain 10-15 seconds of silence at the end of the song, and I try to find from the analyzer when the song has been silent for 5 seconds and acts on it.

So far I have this:

var context, analyser, source, audio; context = new (window.AudioContext || window.webkitAudioContext)(); analyser = context.createAnalyser(); audio = new Audio(); source = context.createMediaElementSource(audio) source.connect(analyser); analyser.connect(context.destination); var playNext = function() { var pickedSong; // chooses a song from an api with several // thousands of songs and store it in pickedSong audio.src = pickedSong; audio.play(); } audio.addEventListener('ended', playNext); playNext(); 

I know that the answer is somewhere in the analyzer, but I did not find any consistency in the data returned from it.

I can do something like this:

 var frequencies = new Float32Array(analyser.frequencyBinCount); analyser.getFloatFrequencyData(frequencies); 

and the var frequencies will contain 2048 keys, each with a random number (-48.11, -55, -67, etc.), do these numbers mean anything related to the perceived sound that is playing ?, how do I I can determine if this is enough so that people do not think that nothing is playing.

For detection, I basically want something like this:

 var isInSilence = function(){ return !audible; } var tries = 0; var checker = function() { tries = isInSilence() ? tries + 1 : 0; if(tries >= 5) playNext(); setTimeout(checker, 1000); } checker(); 

The only missing part is finding out when the song is currently inactive or not, any help would be appreciated.

Edit:

based on william's answer, I managed to solve it by doing this as follows:

 var context, compressor, gain, source, audio; context = new (window.AudioContext || window.webkitAudioContext)(); compressor = context.createDynamicsCompressor(); gain = context.createGain(); audio = new Audio(); source = context.createMediaElementSource(audio) // Connecting source directly source.connect(context.destination); // Connecting source the the compresor -> muted gain source.connect(compressor); compressor.connect(gain); gain.connect(context.destination); gain.gain.value = 0; // muting the gain compressor.threshold.value = -100; var playNext = function() { var pickedSong; // chooses a song from an api with several // thousands of songs and store it in pickedSong audio.src = pickedSong; audio.play(); } audio.addEventListener('ended', playNext); playNext(); var isInSilence = function(){ return compressor.reduction.value >= -50; } var tries = 0; var checker = function() { tries = isInSilence() ? tries + 1 : 0; if(tries >= 5) playNext(); setTimeout(checker, 1000); } checker(); 
+6
source share
2 answers

This is a possible solution using a different approach - the node compressor. This is a short description, but should be enough so that you can fill in the details for your use case:

Create a node compressor and connect an input source to it. Then connect the compressor to the node gain and turn off the node gain (set it to zero). Connect the node gain to the value of audioContext.destination

Take your input source and connect it to audioContext.destination .

Set compressor properties to detect the signal (so that it triggers a reduction value).

Wrap compressor.reduction.value in setInterval or requestAnimationFrame to check for changes.

Enter the logic necessary to perform any action when this value changes (or does not change).

+4
source

For future reference, the values ​​returned by the analyzer for getFloatFrequencyValues ​​are the decibels of this particular signal, so "0" will be a hypothetical full signal, "-96" well below the normal dynamic range for humans.

It will probably be easier for you to use getByteFrequencyValues, which first translates the values ​​to 0-255; 0 - reasonable noise level. If you are looking for REAL silence, just look for zeros in all analyzer cells - if you are looking for a quiet signal, the default -100 for minDecibels is probably too low, so look for a small number (10 or less you will have to experiment). Or change minDecibels - see the specification.

+1
source

All Articles