Created
February 20, 2022 17:53
-
-
Save leemartin/7b36eb9a325e0e4ee45e61bd9ab2a54a to your computer and use it in GitHub Desktop.
Vue Paper.js Audio Spectrum Visualizer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div id="spectrum"> | |
<canvas ref="canvas"></canvas> | |
</div> | |
</template> | |
<script> | |
import paper from 'paper' | |
export default { | |
data() { | |
return { | |
analyser: null, | |
parentHeight: 0, | |
parentWidth: 0, | |
timeArray: null | |
} | |
}, | |
props: { | |
stream: undefined | |
}, | |
methods: { | |
initializePaper() { | |
// Get canvas | |
let canvas = this.$refs.canvas | |
// Get parent size | |
let { height, width } = this.$el.getBoundingClientRect() | |
// Store size | |
this.parentHeight = height | |
this.parentWidth = width | |
// Resize canvas | |
canvas.height = height | |
canvas.width = width | |
// Setup paper | |
paper.setup(canvas) | |
// Create path | |
this.path = new paper.Path({ | |
selected: false | |
}) | |
// Set path stroke to black | |
this.path.strokeColor = '#000000' | |
// Set path width | |
this.path.strokeWidth = 2 | |
}, | |
resizeCanvas() { | |
// Get canvas | |
let canvas = this.$refs.canvas | |
// Get parent size | |
let { height, width } = this.$el.getBoundingClientRect() | |
// Store size | |
this.parentHeight = height | |
this.parentWidth = width | |
// Resize canvas | |
canvas.height = height | |
canvas.width = width | |
// Resize paper | |
paper.view.viewSize = new paper.Size(width, height) | |
}, | |
initializeAnalyzer() { | |
// Create new audio context | |
let context = new AudioContext() | |
// Initialize stream source for microphone | |
let microphone = context.createMediaStreamSource(this.stream) | |
// Initialize analyzer | |
this.analyser = context.createAnalyser() | |
// Set FFT size | |
this.analyser.fftSize = 32 | |
// Get buffer length | |
let bufferLength = this.analyser.frequencyBinCount | |
// Initialize time array | |
this.timeArray = new Uint8Array(bufferLength) | |
// Connect microphone to analyzer | |
microphone.connect(this.analyser) | |
// Start analysis? | |
this.startAnalysis() | |
}, | |
analyze() { | |
// Get data | |
this.analyser.getByteTimeDomainData(this.timeArray) | |
// Update levels from time array | |
let levels = Array.from(this.timeArray).map(t => { | |
return t / 128 | |
}) | |
// Remove segments | |
this.path.removeSegments() | |
// Create segments array from levels | |
let segments = levels.map((level, i) => { | |
return [ | |
i / (levels.length - 1) * this.parentWidth, | |
level * this.parentHeight / 2 | |
] | |
}) | |
// Add segments | |
this.path.addSegments(segments) | |
// Request animation frame | |
this.analysis = requestAnimationFrame(this.analyze) | |
}, | |
startAnalysis() { | |
// Start analysis | |
this.analysis = requestAnimationFrame(this.analyze) | |
}, | |
stopAnalysis() { | |
// Stop analysis | |
cancelAnimationFrame(this.analysis) | |
} | |
}, | |
beforeDestroy() { | |
// Stop analysis | |
this.stopAnalysis() | |
}, | |
mounted() { | |
// Initialize paper | |
this.initializePaper() | |
// Initialize analyzer | |
this.initializeAnalyzer() | |
} | |
} | |
</script> | |
<style lang="postcss" scoped> | |
#spectrum{ | |
height: 100%; | |
width: 100%; | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment