Skip to content

Instantly share code, notes, and snippets.

@leemartin
Created February 20, 2022 17:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leemartin/7b36eb9a325e0e4ee45e61bd9ab2a54a to your computer and use it in GitHub Desktop.
Save leemartin/7b36eb9a325e0e4ee45e61bd9ab2a54a to your computer and use it in GitHub Desktop.
Vue Paper.js Audio Spectrum Visualizer
<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