| /* |
| * Copyright 2016 Boris Smus. All Rights Reserved. |
| |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // Adapted from Boris Smus's demo at http://webaudioapi.com/samples/visualizer |
| |
| /* globals AudioContext, webkitAudioContext */ |
| |
| const WIDTH = 308; |
| const HEIGHT = 231; |
| |
| // Interesting parameters to tweak! |
| const SMOOTHING = 0.8; |
| const FFT_SIZE = 2048; |
| |
| function StreamVisualizer(remoteStream, canvas) { |
| console.log('Creating StreamVisualizer with remoteStream and canvas: ', |
| remoteStream, canvas); |
| this.canvas = canvas; |
| this.drawContext = this.canvas.getContext('2d'); |
| |
| // cope with browser differences |
| if (typeof AudioContext === 'function') { |
| this.context = new AudioContext(); |
| } else if (typeof webkitAudioContext === 'function') { |
| this.context = new webkitAudioContext(); // eslint-disable-line new-cap |
| } else { |
| alert('Sorry! Web Audio is not supported by this browser'); |
| } |
| |
| // Create a MediaStreamAudioSourceNode from the remoteStream |
| this.source = this.context.createMediaStreamSource(remoteStream); |
| console.log('Created Web Audio source from remote stream: ', this.source); |
| |
| this.analyser = this.context.createAnalyser(); |
| // this.analyser.connect(this.context.destination); |
| this.analyser.minDecibels = -140; |
| this.analyser.maxDecibels = 0; |
| this.freqs = new Uint8Array(this.analyser.frequencyBinCount); |
| this.times = new Uint8Array(this.analyser.frequencyBinCount); |
| |
| this.source.connect(this.analyser); |
| |
| this.startTime = 0; |
| this.startOffset = 0; |
| } |
| |
| StreamVisualizer.prototype.start = function() { |
| requestAnimationFrame(this.draw.bind(this)); |
| }; |
| |
| StreamVisualizer.prototype.draw = function() { |
| let barWidth; |
| let offset; |
| let height; |
| let percent; |
| let value; |
| this.analyser.smoothingTimeConstant = SMOOTHING; |
| this.analyser.fftSize = FFT_SIZE; |
| |
| // Get the frequency data from the currently playing music |
| this.analyser.getByteFrequencyData(this.freqs); |
| this.analyser.getByteTimeDomainData(this.times); |
| |
| |
| this.canvas.width = WIDTH; |
| this.canvas.height = HEIGHT; |
| // Draw the frequency domain chart. |
| for (let i = 0; i < this.analyser.frequencyBinCount; i++) { |
| value = this.freqs[i]; |
| percent = value / 256; |
| height = HEIGHT * percent; |
| offset = HEIGHT - height - 1; |
| barWidth = WIDTH / this.analyser.frequencyBinCount; |
| let hue = i/this.analyser.frequencyBinCount * 360; |
| this.drawContext.fillStyle = 'hsl(' + hue + ', 100%, 50%)'; |
| this.drawContext.fillRect(i * barWidth, offset, barWidth, height); |
| } |
| |
| // Draw the time domain chart. |
| for (let i = 0; i < this.analyser.frequencyBinCount; i++) { |
| value = this.times[i]; |
| percent = value / 256; |
| height = HEIGHT * percent; |
| offset = HEIGHT - height - 1; |
| barWidth = WIDTH/this.analyser.frequencyBinCount; |
| this.drawContext.fillStyle = 'white'; |
| this.drawContext.fillRect(i * barWidth, offset, 1, 2); |
| } |
| |
| requestAnimationFrame(this.draw.bind(this)); |
| }; |
| |
| StreamVisualizer.prototype.getFrequencyValue = function(freq) { |
| let nyquist = this.context.sampleRate/2; |
| let index = Math.round(freq/nyquist * this.freqs.length); |
| return this.freqs[index]; |
| }; |