Detecting frequencies of mp3 file in JS in non real time - javascript

I want to get the frequencies of an audio file with JS in non-real-time, e.g before the file is played, and store it in an array.
I used this code:
var context = new AudioContext();
src = context.createMediaElementSource(source);
analyser = context.createAnalyser();
var listen = context.createGain();
src.connect(listen);
listen.connect(analyser);
analyser.connect(context.destination);
analyser.fftSize = 2 ** 12;
var frequencyBins = analyser.fftSize / 2;
var bufferLength = analyser.frequencyBinCount;
console.log(bufferLength);
dataArray = new Float32Array(bufferLength);
// dataArray = new Uint8Array(bufferLength);
var scale = bufferLength/WIDTH;
And then in an animation frame,
dataArraya = new Float32Array(2048);
analyser.getFloatFrequencyData(dataArraya)
This works great in real-time, but I'd like to get the audio data before, how can I do that?

Related

unable to double the volume of audio

I want to play only the audio of a mp4 video file. So far I'm here and this function works fine without any errors:
function MovieAudio() {
const video = document.createElement('video');
document.body.appendChild(video);
video.id = 'clip';
const clip = document.getElementById("clip");
clip.style.visibility = "hidden";
const source = document.createElement('source');
source.src = 'myvideo.mp4';
source.type = 'video/mp4';
video.appendChild(source);
video.load();
clip.volume = 1;
clip.play();
} // end of MovieAudio function
The problem is I want to double the volume of the audio and if I set the volume like this I get an error:
clip.volume = 2;
I find a solution here but I can't make the code work...
https://stackoverflow.com/a/43794379/10715551
// create an audio context and hook up the video element as the source
var audioCtx = new AudioContext();
var source = audioCtx.createMediaElementSource(clip);
// create a gain node
var gainNode = audioCtx.createGain();
gainNode.gain.value = 2; // double the volume
source.connect(gainNode);
// connect the gain node to an output destination
gainNode.connect(audioCtx.destination);
How can I double the volume of audio with the given code?

Get fft data of a audio file in JavaScript?

In real-time we do this to get the frequency of the audio while audio is playing.
Window.onload{
audio.load();
audio.play();
Var context = new audioContext();
Context.createMediaElementSource(audio);
Var analyser = context.createAnalyser();
analyser.fftsize = 512;
Var array = new uintarray(analyser.frequencyBinCount);
Function render(){
RequestAnimationFrame(render);
analyser.getFrequencyBinCount(array);
//Process frequency details here
}
I want to get a frequency of an audio clip 30 times a second in nonreal time.
for example
Var subSecond = 1/30;
Var frequency = getFrequencyAt(64*subSecond);
Function getFrequencyAt(s){
//Logic to get the frequency here
}
How can I achieve this efficiently?

HTML5 Audio - Getting frequency array full of zeros

I'm having a bit of a trouble building an Audio frequency visualization. I am using HTML5 audio tag:
<audio id="music" src="https://cdn.glitch.com/02dcea11-9bd2-4462-ac38-eeb6a5ad9530%2F331_full_beautiful-minds_0171_preview.mp3?1522829295082" crossorigin="use-URL-credentials" controls="true"></audio>
(song is from www.premiumbeat.com)
used with AudioContext and Analyser as shown below:
const audio = document.getElementById('music');
audio.load();
audio.play();
const ctx = new AudioContext();
const audioSrc = ctx.createMediaElementSource(audio);
const analyser = ctx.createAnalyser();
audioSrc.connect(analyser);
analyser.connect(ctx.destination);
analyser.fftSize = 256;
const bufferLength = analyser.frequencyBinCount;
const frequencyData = new Uint8Array(bufferLength);
analyser.getByteFrequencyData(frequencyData);
setTimeout(() => {
analyser.getByteFrequencyData(frequencyData);
console.log(frequencyData);
}, 5000);
Output:
Even though the song is playing when I call the getByteFrequencyData(), the output is 128 items long array full of zeros.
Expected behaviour:
After 5 seconds console should output 128 items long array of current frequency data. (I do it this way because requestAnimationFrame would lag the window, however I tried it and the result is the same).
Any idea what I do wrong? (I'm using Firefox Quantum 59.0.2.)
Try it here: JSFiddle example
Thank you!
Following my experiments with the web audio api i modified your script to use getByteTimeDomainData instead of getByteFrequencyData.
https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode/getByteTimeDomainData
Using intervals instead of timeout for the demo.
const audio = document.getElementById('music');
audio.load();
audio.play();
const ctx = new AudioContext();
const audioSrc = ctx.createMediaElementSource(audio);
const analyser = ctx.createAnalyser();
audioSrc.connect(analyser);
analyser.connect(ctx.destination);
analyser.fftSize = 256;
const bufferLength = analyser.frequencyBinCount;
const frequencyData = new Uint8Array(bufferLength);
setInterval(() => {
analyser.getByteFrequencyData(frequencyData);
console.log(frequencyData);
}, 1000);
<audio id="music" src="https://cdn.glitch.com/02dcea11-9bd2-4462-ac38-eeb6a5ad9530%2F331_full_beautiful-minds_0171_preview.mp3?1522829295082" crossorigin="use-URL-credentials" controls="true"></audio>

Surround sound (5.1) Web Audio support

I'm trying to create simple aplication to play stereo / mono music in all 5.1 channels. After studying Web audio specification I spend 4 hours to try code it. Unfortunately I got nowhere. Audio is playing only over 2 channels. If I set merger.channelCountMode = "explicit" it plays only from center channel.
If I set merger.channelInterpretation = "discrete"; it plays only from left channel. What I'm doing wrong? Thank you very much.
My code:
var audio;
function PlaySurround(){
context = new AudioContext();
audio = new Audio();
audio.src = "a.mp3";
var source = context.createMediaElementSource(audio);
context.destination.channelCount = 6;
audio.currentTime = Math.random() * 200;
//Create a splitter to "separete" the stereo audio data to two channels.
var splitter = context.createChannelSplitter(6);
splitter.channelCount = 6;
//splitter.channelInterpretation = "discrete";
//splitter.channelCountMode = "explicit";
console.log(splitter);
//Connect your source to the splitter (usually, you will do it with the last audio node before context destination)
source.connect(splitter);
//Create two gain nodes (one for each side of the stereo image)
var panLeft = context.createGain();
var panRight = context.createGain();
var panLeftSurround = context.createGain();
var panRightSurround = context.createGain();
var panCenter = context.createGain();
var panSubwoofer = context.createGain();
//Connect the splitter channels to the Gain Nodes that we've just created
splitter.connect(panLeft, 0);
splitter.connect(panRight, 1);
splitter.connect(panCenter, 2);
splitter.connect(panSubwoofer, 3);
splitter.connect(panLeftSurround, 4);
splitter.connect(panRightSurround, 5);
panLeft.gain.value = 1;
panRight.gain.value = 1;
panLeftSurround.gain.value = 1;
panRightSurround.gain.value = 1;
panCenter.gain.value = 1;
panSubwoofer.gain.value = 1;
//Create a merger node, to get both signals back together
var merger = context.createChannelMerger(6);
merger.channelCount = 6;
//merger.channelInterpretation = "discrete";
merger.channelCountMode = "explicit";
console.log(merger);
panLeft.connect(merger, 0, 0);
panRight.connect(merger, 0, 1);
panCenter.connect(merger, 0, 2);
panSubwoofer.connect(merger, 0, 3);
panLeftSurround.connect(merger, 0, 4);
panRightSurround.connect(merger, 0, 5);
//Connect the Merger Node to the final audio destination (your speakers)
merger.connect(context.destination);
source.mediaElement.play();
}

Stereo convolution with web audio

I'm trying to convolve a mono impulse with a stereo audio file using the web audio api. The problem is instead of getting true stereo output, I'm getting what looks and sounds like the same track duplicated to both channels. Here's my code:
var context = new AudioContext();
var source = context.createBufferSource();
source.buffer = BUFFERS.user; // stereo file
var splitter = context.createChannelSplitter(2);
var convolverL = context.createConvolver();
convolverL.normalize = false;
convolverL.buffer = BUFFERS.impulse; // mono impulse
var convolverR = context.createConvolver();
convolverR.normalize = false;
convolverR.buffer = BUFFERS.impulse; // same mono impulse
var merger = context.createChannelMerger(2);
var gain = context.createGain();
gain.gain.value = 0.75;
// make connections
source.connect(splitter);
splitter.connect(convolverL, 0);
splitter.connect(convolverR, 1);
convolverL.connect(merger, 0, 0);
convolverR.connect(merger, 0, 1);
merger.connect(gain);
gain.connect(context.destination);
source.start(0);

Categories