Skip to content

Commit

Permalink
Fix: web audio examples + update lint (#3968)
Browse files Browse the repository at this point in the history
  • Loading branch information
katspaugh authored Dec 25, 2024
1 parent 14bb9a3 commit e1dabf2
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 51 deletions.
77 changes: 36 additions & 41 deletions examples/webaudio.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,72 +2,67 @@

import WaveSurfer from 'wavesurfer.js'

// Create your own media element
const audio = new Audio()
audio.controls = true
audio.src = '/examples/audio/audio.wav'
// Define the equalizer bands
const eqBands = [32, 64, 125, 250, 500, 1000, 2000, 4000, 8000, 16000]

// Create a WaveSurfer instance and pass the media element
const wavesurfer = WaveSurfer.create({
container: document.body,
waveColor: 'rgb(200, 0, 200)',
progressColor: 'rgb(100, 0, 100)',
media: audio, // <- this is the important part
url: '/examples/audio/audio.wav',
mediaControls: true,
})

// Optionally, add the audio to the page to see the controls
document.body.appendChild(audio)
wavesurfer.on('click', () => wavesurfer.playPause())

// Now, create a Web Audio equalizer
wavesurfer.once('play', () => {
// Create Web Audio context
const audioContext = new AudioContext()

// Create Web Audio context
const audioContext = new AudioContext()
// Create a biquad filter for each band
const filters = eqBands.map((band) => {
const filter = audioContext.createBiquadFilter()
filter.type = band <= 32 ? 'lowshelf' : band >= 16000 ? 'highshelf' : 'peaking'
filter.gain.value = Math.random() * 40 - 20
filter.Q.value = 1 // resonance
filter.frequency.value = band // the cut-off frequency
return filter
})

// Define the equalizer bands
const eqBands = [32, 64, 125, 250, 500, 1000, 2000, 4000, 8000, 16000]
const audio = wavesurfer.getMediaElement()
const mediaNode = audioContext.createMediaElementSource(audio)

// Create a biquad filter for each band
const filters = eqBands.map((band) => {
const filter = audioContext.createBiquadFilter()
filter.type = band <= 32 ? 'lowshelf' : band >= 16000 ? 'highshelf' : 'peaking'
filter.gain.value = Math.random() * 40 - 20
filter.Q.value = 1 // resonance
filter.frequency.value = band // the cut-off frequency
return filter
})

// Connect the audio to the equalizer
audio.addEventListener(
'canplay',
() => {
// Create a MediaElementSourceNode from the audio element
const mediaNode = audioContext.createMediaElementSource(audio)
// Connect the filters and media node sequentially
const equalizer = filters.reduce((prev, curr) => {
prev.connect(curr)
return curr
}, mediaNode)

// Connect the filters and media node sequentially
const equalizer = filters.reduce((prev, curr) => {
prev.connect(curr)
return curr
}, mediaNode)
// Connect the filters to the audio output
equalizer.connect(audioContext.destination)

// Connect the filters to the audio output
equalizer.connect(audioContext.destination)
},
{ once: true },
)
sliders.forEach((slider, i) => {
const filter = filters[i]
filter.gain.value = slider.value
slider.oninput = (e) => (filter.gain.value = e.target.value)
})
})

// HTML UI
// Create a vertical slider for each band
const container = document.createElement('p')
filters.forEach((filter) => {
const sliders = eqBands.map(() => {
const slider = document.createElement('input')
slider.type = 'range'
slider.orient = 'vertical'
slider.style.appearance = 'slider-vertical'
slider.style.width = '8%'
slider.min = -40
slider.max = 40
slider.value = filter.gain.value
slider.value = Math.random() * 40 - 20
slider.step = 0.1
slider.oninput = (e) => (filter.gain.value = e.target.value)
container.appendChild(slider)
return slider
})
document.body.appendChild(container)
8 changes: 6 additions & 2 deletions src/plugins/regions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,11 @@ class SingleRegion extends EventEmitter<RegionEvents> implements Region {
public contentEditable = false
public subscriptions: (() => void)[] = []

constructor(params: RegionParams, private totalDuration: number, private numberOfChannels = 0) {
constructor(
params: RegionParams,
private totalDuration: number,
private numberOfChannels = 0,
) {
super()

this.subscriptions = []
Expand Down Expand Up @@ -263,7 +267,7 @@ class SingleRegion extends EventEmitter<RegionEvents> implements Region {
() => this.toggleCursor(true),
() => {
this.toggleCursor(false)
this.drag && this.emit('update-end')
if (this.drag) this.emit('update-end')
},
),
)
Expand Down
11 changes: 3 additions & 8 deletions src/plugins/timeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export type TimelinePluginOptions = {
/** Interval between secondary numeric labels in timeIntervals (i.e notch count) */
secondaryLabelSpacing?: number
/** offset in seconds for the numeric labels */
timeOffset?: number
timeOffset?: number
/** Custom inline style to apply to the container */
style?: Partial<CSSStyleDeclaration> | string
/** Turn the time into a suitable label for the time. */
Expand All @@ -36,6 +36,7 @@ export type TimelinePluginOptions = {

const defaultOptions = {
height: 20,
timeOffset: 0,
formatTimeCallback: (seconds: number) => {
if (seconds / 60 > 1) {
// calculate minutes and seconds from seconds count
Expand Down Expand Up @@ -145,11 +146,6 @@ class TimelinePlugin extends BasePlugin<TimelinePluginEvents, TimelinePluginOpti
return 2
}

// Return how many seconds the labels are offset.
private defaultTimeOffset(pxPerSec: number): number {
return 0;
}

private virtualAppend(start: number, container: HTMLElement, element: HTMLElement) {
let wasVisible = false

Expand Down Expand Up @@ -189,7 +185,6 @@ class TimelinePlugin extends BasePlugin<TimelinePluginEvents, TimelinePluginOpti
const primaryLabelSpacing = this.options.primaryLabelSpacing
const secondaryLabelInterval = this.options.secondaryLabelInterval ?? this.defaultSecondaryLabelInterval(pxPerSec)
const secondaryLabelSpacing = this.options.secondaryLabelSpacing
const timeOffset = this.options.timeOffset ?? this.defaultTimeOffset(pxPerSec)
const isTop = this.options.insertPosition === 'beforebegin'

const timeline = createElement('div', {
Expand Down Expand Up @@ -256,7 +251,7 @@ class TimelinePlugin extends BasePlugin<TimelinePluginEvents, TimelinePluginOpti
const mode = isPrimary ? 'primary' : isSecondary ? 'secondary' : 'tick'
notch.setAttribute('part', `timeline-notch timeline-notch-${mode}`)

const offset = (i + timeOffset) * pxPerSec
const offset = (i + this.options.timeOffset) * pxPerSec
notch.style.left = `${offset}px`
this.virtualAppend(offset, timeline, notch)
}
Expand Down

0 comments on commit e1dabf2

Please sign in to comment.