Closed tutaru99 closed 3 years ago
Hello! Thank you for your question.
Isn't the first frame silent?
Even in the sample code, there is no sound in the first frame, so the values of the array that can be obtained first are all 0.
At the same time as the music starts playing, requestAnimationFrame
is used to execute getByteFrequencyData
every frame to get an array of waveform data at the moment when the sound is sounding.
// Draw SVG for audio visualizer
drawAudioVisualizer(){
// Animation ends when gain reaches 0
if(this.gainNode.gain.value === 0){
if(this.drawTimer){
window.cancelAnimationFrame(this.drawTimer);
return;
}
}
// Set 0 to 1. Drawing becomes smoother when it is closer to 0
this.analyserNode.smoothingTimeConstant = 0.1;
// FFT size
this.analyserNode.fftSize = 1024;
// Store the waveform data in the frequency domain in an array of arguments
this.analyserNode.getByteFrequencyData(this.freqs);
// How long the SVG width will be with respect to the waveform data
const barWidth = this.svg.width.baseVal.value * 1.5 / this.analyserNode.frequencyBinCount;
// Apply width calculation result to SVG path
this.drawSvgPath(barWidth);
// Draw every frame
this.drawTimer = window.requestAnimationFrame(this.drawAudioVisualizer.bind(this));
}
As mentioned above, the function is recursively called to work with the animation.
Also, I think fftsize
is fftSize
.
Hey! Thanks for the quick reply and help!
I've tried to implement your code however I couldn't make it work. I've changed my code quite a bit, but I think the problem I'm having is that I'm not fully/or at all connected to the howler. I keep getting 0 on the getByteFrequencyData.
2 Main functions that I'm using is startRadio()
and drawAudioVisualizer()
even though drawAudioVisualizer()
right now is used just to show frequency data.
startRadio(stationSrc, stationID) {
this.radioStarted = true;
this.arrayID = stationID;
this.stations[stationID].playing = true;
this.sound = new Howl({
src: stationSrc,
html5: true,
volume: this.volume,
});
// Create an analyser node in the Howler WebAudio context
var analyser = Howler.ctx.createAnalyser();
var dataArray = new Uint8Array(analyser.frequencyBinCount);
Howler.ctx.createGain = Howler.ctx.createGain || Howler.ctx.createGainNode;
var gainNode = Howler.ctx.createGain();
gainNode.gain.setValueAtTime(1, Howler.ctx.currentTime);
Howler.masterGain.connect(analyser);
analyser.connect(gainNode);
gainNode.connect(Howler.ctx.destination);
// Starting Playing Audio
this.soundID = this.sound.play();
console.log("Radio Started Playing");
// Defining variables so they can be used globally
this.analyser = analyser;
this.gainNode = gainNode;
this.frequency = dataArray;
// Call function to show frequency data
this.drawAudioVisualizer();
},
Function to get frequency data when audio is playing
// Start getting Frequency Data
drawAudioVisualizer(){
// Animation ends when gain reaches 0
if(this.gainNode.gain.value === 0){
if(this.drawTimer){
window.cancelAnimationFrame(this.drawTimer);
return;
}
}
// Set 0 to 1. Drawing becomes smoother when it is closer to 0
this.analyser.smoothingTimeConstant = 0.1;
// FFT size
this.analyser.fftSize = 1024;
// Store the waveform data in the frequency domain in an array of arguments
this.analyser.getByteFrequencyData(this.frequency);
// Draw every frame
this.drawTimer = window.requestAnimationFrame(this.drawAudioVisualizer.bind(this));
console.log(this.frequency)
},
Console Output on frequency
As shown in the picture above, the recursive function starts (and works?) however I keep getting 0 for frequency - getByteFrequencyData even when audio is playing.
This leads me to believe that I'm not connected to the parts of howler that I need to..?
Perhaps you can spot what I'm missing in the code? I believe the problem lies in the startRadio() {}
function.
Thanks for taking the time to help me out.
Maybe there is a problem with the option settings in Howler.js.
html5: true
By specifying this option, Howler.js will play using HTML5 Audio instead of the Web Audio API.
Web Audio API https://webaudio.github.io/web-audio-api/
HTML5 Audio https://html.spec.whatwg.org/multipage/media.html#the-audio-element
HTML5 Audio and Web Audio API are completely different, so
// Create an analyzer node in the Howler WebAudio context
The code after the comment line above will not work.
Even in my sample code, setting html5: true
makes a sound but the visualizer doesn't work.
So after a lot of testing and searching, I came to a conclusion that I simply cannot use live stream audio from the internet radio station and in turn get its frequency. As you mentioned above html5: true
is the culprit of the problem.
Without it - and with minor code adjustment + a local song - var sound = new Howl({ src: require('@/assets/audio.mp3')});
I start getting frequency just fine. However again I want frequency from Live Streaming Radio which requires me to use html5: true
in order to make it work. Therefore I came to realization that I simply can't do this the way I want.. :D
Thanks for helping me and explaining this audio concept!
If you want to handle streaming sound sources
You may need to use AudioContext.createMediaStreamSource()
.
https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/createMediaStreamSource
I don't know how much it can be done with Howler.js, but some people use the plain Web Audio API to visualize the audio picked up from the microphone.
https://github.com/aadebdeb/web-audio-gl-sample
I hope it will be helpful. Good luck!
Hello, I need help with the implementation of the visualizer into my own project - radio.
The biggest issue I'm having right now - getByteFrequencyData() returns a full array of 0 no matter what.
Thanks, have a good one. (Feel free to contact me through email, it's on my GitHub page) Code:
Output:![output](https://user-images.githubusercontent.com/43951824/126064261-c209f9ed-152e-4cb2-9805-9a330e761873.png)