Skip to content

EZ Web Audio / BeatTrack

Class: BeatTrack ​

Defined in: packages/core/src/beat-track.ts:55

Drum machine lane with rhythmic beat patterns.

BeatTrack manages an array of Beat instances for creating drum patterns. It extends Sampler for round-robin sample variation and adds tempo-synced playback with beat events for visual synchronization.

Example ​

typescript
import { createBeatTrack } from 'ez-web-audio'

const kick = await createBeatTrack(['kick.mp3'], { numBeats: 8 })

// Set a basic 4-on-the-floor pattern
kick.beats[0].active = true  // beat 1
kick.beats[2].active = true  // beat 3
kick.beats[4].active = true  // beat 5
kick.beats[6].active = true  // beat 7

kick.playBeats(120, 1/4) // Play quarter notes at 120 BPM

// Listen for beat events
kick.on('beat', (e) => {
  console.log(`Beat ${e.detail.beatIndex}`)
})

Extends ​

Implements ​

  • SyncableBeatTrack

Constructors ​

Constructor ​

new BeatTrack(audioContext, sounds, opts?): BeatTrack

Defined in: packages/core/src/beat-track.ts:118

Parameters ​

audioContext ​

AudioContext

sounds ​

Playable & Connectable[]

opts? ​

BeatTrackOptions

Returns ​

BeatTrack

Overrides ​

Sampler.constructor

Properties ​

duration ​

duration: number = 100

Defined in: packages/core/src/beat-track.ts:154

How long (in milliseconds) the isPlaying flag stays true after a beat plays. Useful for visual feedback in the UI.

Default ​

ts
100

muted ​

muted: boolean = false

Defined in: packages/core/src/beat-track.ts:100

Whether this track is muted. When muted, beat scheduling continues (events still fire for UI sync) but audio playback is silenced.


name ​

name: string

Defined in: packages/core/src/sampler.ts:53

Optional name to aid in identification.

Inherited from ​

Sampler.name


numBeats ​

numBeats: number = 4

Defined in: packages/core/src/beat-track.ts:147

Number of beats in this track.

Default ​

ts
4

solo ​

solo: boolean = false

Defined in: packages/core/src/beat-track.ts:107

Whether this track is soloed. Solo is stackable — when any synced track has solo=true, only soloed tracks produce audio. When no tracks are soloed, all unmuted tracks produce audio.

Accessors ​

beats ​

Get Signature ​

get beats(): Beat[]

Defined in: packages/core/src/beat-track.ts:174

Array of Beat instances in this track.

The array length always matches numBeats. Beats are reused when the count changes, preserving their active state.

Example ​
typescript
// Toggle individual beats
track.beats[0].active = true
track.beats[1].active = false

// Check all beat states
track.beats.forEach((beat, i) => {
  console.log(`Beat ${i}: ${beat.active ? 'on' : 'off'}`)
})
Returns ​

Beat[]

Implementation of ​

SyncableBeatTrack.beats


gain ​

Get Signature ​

get gain(): number

Defined in: packages/core/src/sampler.ts:75

Gain level applied to each sample when played. This value is applied to the underlying Sound on every play() call, overriding any per-sound gain customization.

Validated the same way as Sampler.changeGainTo / BaseSound.changeGainTo: throws a ValidationError for negative values, warns on the console for values above 1 (R1#1 — previously this was a raw mutable field with no validation at all). Defaults to 1.

Returns ​

number

Set Signature ​

set gain(value): void

Defined in: packages/core/src/sampler.ts:79

Parameters ​
value ​

number

Returns ​

void

Inherited from ​

Sampler.gain


isSynced ​

Get Signature ​

get isSynced(): boolean

Defined in: packages/core/src/beat-track.ts:411

Whether this BeatTrack is currently synced to a Transport.

Returns ​

boolean


pan ​

Get Signature ​

get pan(): number

Defined in: packages/core/src/sampler.ts:92

Stereo pan position applied to each sample (-1 = left, 0 = center, 1 = right). This value is applied to the underlying Sound on every play() call, overriding any per-sound pan customization.

Validated the same way as Sampler.changePanTo / BaseSound.changePanTo: warns on the console for values outside [-1, 1] (R1#1). Defaults to 0.

Returns ​

number

Set Signature ​

set pan(value): void

Defined in: packages/core/src/sampler.ts:96

Parameters ​
value ​

number

Returns ​

void

Inherited from ​

Sampler.pan

Methods ​

addEventListener() ​

addEventListener<K>(type, listener, options?): void

Defined in: packages/core/src/beat-track.ts:710

Add a typed event listener for BeatTrack lifecycle events.

Type Parameters ​

K ​

K extends keyof BeatTrackEventMap

Parameters ​

type ​

K

Event type: 'beat', 'stop', 'pause', 'resume'

listener ​

(event) => void

Handler function

options? ​

Standard addEventListener options

boolean | AddEventListenerOptions

Returns ​

void


changeGainTo() ​

changeGainTo(value): this

Defined in: packages/core/src/sampler.ts:108

Set the gain level applied to each sample. Equivalent to sampler.gain = value, provided for API symmetry with BaseSound.changeGainTo() / LayeredSound.changeGainTo().

Parameters ​

value ​

number

The gain value (0-1 typical range)

Returns ​

this

this for chaining

Inherited from ​

Sampler.changeGainTo


changePanTo() ​

changePanTo(value): this

Defined in: packages/core/src/sampler.ts:120

Set the pan position applied to each sample. Equivalent to sampler.pan = value, provided for API symmetry with BaseSound.changePanTo() / LayeredSound.changePanTo().

Parameters ​

value ​

number

The pan value (-1 to 1)

Returns ​

this

this for chaining

Inherited from ​

Sampler.changePanTo


dispose() ​

dispose(): void

Defined in: packages/core/src/beat-track.ts:747

Dispose this BeatTrack, stopping playback, clearing beats, and releasing all audio resources.

After disposal, the BeatTrack should not be used. Create a new instance instead.

Returns ​

void

Example ​

typescript
const track = await createBeatTrack(['kick.mp3'], { numBeats: 8 })
track.playBeats(120, 1/4)
// When done:
track.dispose()

getSounds() ​

getSounds(): readonly Playable & Connectable[]

Defined in: packages/core/src/sampler.ts:208

Get a readonly snapshot of the sampler's sounds.

Returns a shallow copy as an array so callers can inspect which sounds are loaded without mutating the internal Set.

Returns ​

readonly Playable & Connectable[]

Readonly array of sounds in the sampler

Example ​

typescript
const sampler = await createSampler(['kick-1.mp3', 'kick-2.mp3'])
const sounds = sampler.getSounds()
console.log(sounds.length) // 2

Inherited from ​

Sampler.getSounds


off() ​

off<K>(type, listener): this

Defined in: packages/core/src/beat-track.ts:806

Unsubscribe from an event. Supports chaining.

Type Parameters ​

K ​

K extends keyof BeatTrackEventMap

Parameters ​

type ​

K

Event type to unsubscribe from

listener ​

(event) => void

Handler function to remove

Returns ​

this

this for chaining


on() ​

on<K>(type, listener): this

Defined in: packages/core/src/beat-track.ts:791

Subscribe to an event. Supports chaining.

Type Parameters ​

K ​

K extends keyof BeatTrackEventMap

Parameters ​

type ​

K

Event type: 'beat', 'stop', 'pause', 'resume'

listener ​

(event) => void

Handler function

Returns ​

this

this for chaining

Example ​

typescript
track.on('beat', (e) => {
  console.log(`Beat ${e.detail.beatIndex}`)
  highlightBeat(e.detail.beatIndex)
}).on('stop', () => {
  console.log('Stopped')
})

once() ​

once<K>(type, listener): this

Defined in: packages/core/src/beat-track.ts:828

Subscribe to an event once. Handler is removed after first invocation.

Type Parameters ​

K ​

K extends keyof BeatTrackEventMap

Parameters ​

type ​

K

Event type to listen for

listener ​

(event) => void

Handler function (called only once)

Returns ​

this

this for chaining

Example ​

typescript
track.once('stop', () => {
  console.log('Track stopped for the first time')
})

pause() ​

pause(): void

Defined in: packages/core/src/beat-track.ts:340

Pause playback at the current position.

Emits a 'pause' event with the current beat index. Use resume() to continue from where you left off.

Returns ​

void

Example ​

typescript
track.pause()
// later...
track.resume()

play() ​

play(velocity): void

Defined in: packages/core/src/sampler.ts:149

Play the next sound in the rotation immediately.

Parameters ​

velocity ​

number = 1

Gain multiplier (0–1) applied on top of the sampler's gain. Defaults to 1 (no attenuation).

Returns ​

void

Example ​

typescript
sampler.play() // plays sound 1
sampler.play() // plays sound 2
sampler.play(0.4) // plays sound 3 at 40% of the sampler's gain (then wraps to 1)

Inherited from ​

Sampler.play


playActiveBeats() ​

playActiveBeats(bpm, noteType): void

Defined in: packages/core/src/beat-track.ts:292

Start playing only active beats in the pattern continuously.

Same as playBeats(), but only plays beats where active === true. Inactive beats become rests (silence), maintaining timing.

Parameters ​

bpm ​

number

Tempo in beats per minute

noteType ​

number

Rhythmic subdivision as a fraction. Common values: 1/4 (quarter notes), 1/8 (eighth notes), 1/16 (sixteenth notes). The beat duration in seconds is calculated as: (240 * noteType) / bpm.

Returns ​

void

Example ​

typescript
// Set up a pattern with rests
track.beats[0].active = true
track.beats[2].active = true
track.playActiveBeats(120, 1/4)  // Only beats 0 and 2 play

playAt() ​

playAt(time, velocity): void

Defined in: packages/core/src/sampler.ts:186

Play the next sound at a specific AudioContext time.

Parameters ​

time ​

number

The AudioContext.currentTime value when to play

velocity ​

number = 1

Gain multiplier (0–1) applied on top of the sampler's gain. Defaults to 1 (no attenuation).

Returns ​

void

Example ​

typescript
const startTime = audioContext.currentTime + 1
sampler.playAt(startTime) // plays next sound at exactly startTime
sampler.playAt(startTime, 0.8) // plays next sound at exactly startTime at 80% gain

Inherited from ​

Sampler.playAt


playBeats() ​

playBeats(bpm, noteType): void

Defined in: packages/core/src/beat-track.ts:256

Start playing all beats in the pattern continuously.

Starts a lookahead scheduler that triggers beats at precise audio times. Emits 'beat' events for UI synchronization.

Unlike playActiveBeats(), this plays ALL beats regardless of their active flag.

Parameters ​

bpm ​

number

Tempo in beats per minute

noteType ​

number

Rhythmic subdivision as a fraction. Common values: 1/4 (quarter notes), 1/8 (eighth notes), 1/16 (sixteenth notes). The beat duration in seconds is calculated as: (240 * noteType) / bpm.

Returns ​

void

Example ​

typescript
track.playBeats(120, 1/4)  // 120 BPM, quarter notes — all beats play
track.playBeats(140, 1/8)  // 140 BPM, eighth notes

playIn() ​

playIn(seconds, velocity): void

Defined in: packages/core/src/sampler.ts:169

Play the next sound in the rotation after a delay.

Parameters ​

seconds ​

number

Number of seconds from now to play the sound

velocity ​

number = 1

Gain multiplier (0–1) applied on top of the sampler's gain. Defaults to 1 (no attenuation).

Returns ​

void

Example ​

typescript
sampler.playIn(0.5) // plays next sound in 0.5 seconds
sampler.playIn(0.5, 0.6) // plays next sound in 0.5 seconds at 60% gain

Inherited from ​

Sampler.playIn


removeEventListener() ​

removeEventListener<K>(type, listener, options?): void

Defined in: packages/core/src/beat-track.ts:725

Remove a typed event listener.

Type Parameters ​

K ​

K extends keyof BeatTrackEventMap

Parameters ​

type ​

K

Event type to unsubscribe from

listener ​

(event) => void

Handler function to remove

options? ​

Standard removeEventListener options

boolean | EventListenerOptions

Returns ​

void


resume() ​

resume(): void

Defined in: packages/core/src/beat-track.ts:366

Resume playback from where it was paused.

Emits a 'resume' event with the beat index where playback resumes. Has no effect if not paused.

Returns ​

void

Example ​

typescript
track.pause()
// ...user clicks play button...
track.resume() // continues from paused position

setPattern() ​

setPattern(pattern): this

Defined in: packages/core/src/beat-track.ts:227

Set beat active states (and velocities) from a pattern array.

Each element maps to a beat: truthy values (1, true) set the beat active, falsy values (0, false) set it inactive. If the array is shorter than the number of beats, remaining beats are set inactive. If longer, extra values are ignored.

Numeric values greater than 0 also set the beat's velocity — a gain multiplier for that hit (clamped to a max of 1). Booleans, and numbers that are 0 or negative, leave velocity at its current/default value of 1, matching prior boolean-only behavior.

Parameters ​

pattern ​

(number | boolean)[]

Array of numbers (0-1 velocity, or any non-zero value as "on") or booleans representing the beat pattern

Returns ​

this

this for chaining

Example ​

typescript
const kick = await createBeatTrack(['kick.mp3'], { numBeats: 8 })

// 4-on-the-floor pattern
kick.setPattern([1, 0, 1, 0, 1, 0, 1, 0])

// Ghost notes via velocity — 0.6 = quieter hit
kick.setPattern([1, 0, 0.6, 0])

// Shorter array — remaining beats inactive
kick.setPattern([1, 0, 1]) // beats 3-7 become inactive

// Chainable
kick.setPattern([1, 0, 1, 0]).playActiveBeats(120, 1/4)

setTempo() ​

setTempo(bpm): void

Defined in: packages/core/src/beat-track.ts:400

Change the tempo while playing.

The new tempo takes effect on the next scheduled beat.

Parameters ​

bpm ​

number

New tempo in beats per minute

Returns ​

void

Example ​

typescript
track.playBeats(120, 1/4)
// later, speed up...
track.setTempo(140)

stop() ​

stop(): void

Defined in: packages/core/src/beat-track.ts:322

Stop playback and reset to the beginning.

Emits a 'stop' event. Use pause() instead if you want to resume later.

Returns ​

void

Example ​

typescript
track.stop()
track.on('stop', () => console.log('Stopped'))

syncTo() ​

syncTo(transport, opts): void

Defined in: packages/core/src/beat-track.ts:435

Sync this BeatTrack to a Transport for clock-driven playback.

When synced, the Transport's scheduler drives this track's beats. Standalone methods (playBeats, playActiveBeats, stop, pause, resume, setTempo) throw an error while synced — use transport.start()/stop() instead.

Parameters ​

transport ​

Transport

The Transport to sync to

opts ​

Sync options

noteType ​

number

Rhythmic subdivision (e.g., 1/4, 1/16)

Returns ​

void

Example ​

typescript
const transport = await createTransport({ bpm: 120 })
const kick = await createBeatTrack(['kick.mp3'], { numBeats: 4 })

kick.syncTo(transport, { noteType: 1/4 })
transport.start() // kicks play quarter notes at 120 BPM

unsync() ​

unsync(): void

Defined in: packages/core/src/beat-track.ts:457

Unsync this BeatTrack from its Transport.

Re-enables standalone methods (playBeats, playActiveBeats, stop, etc.). If the track was playing via Transport, it stops cleanly.

Returns ​

void

Example ​

typescript
kick.unsync()
kick.playBeats(120, 1/4) // standalone mode works again