Files
suaveplan/openspec/archive/2026-05-23-enterprise-audio-analysis-beat/proposal.md
2026-05-27 23:29:53 +01:00

5.2 KiB

OpenSpec Change: enterprise-audio-analysis-beat

  • Change ID: enterprise-audio-analysis-beat
  • Package: @suaveplan/audio-analysis-beat
  • Category: universal
  • Target path: packages/media/audio/audio-analysis-beat
  • Status: PROPOSED
  • Date: 2026-05-14
  • Design: ./design.md
  • Spec delta: ./specs/audio-analysis-beat/spec.md

Summary

Deliver @suaveplan/audio-analysis-beat on the genesis branch from scratch at enterprise quality. Beat and tempo detection plugin for the universal audio analysis framework. Detects BPM, beat locations, and onset times from AudioDocument streams using energy-based and spectral-flux algorithms, with optional comb-filter tempo estimation and beat-grid alignment.

Runs identically in browser and server via BlockProcessor or direct stream iteration.


Current-state audit (genesis)

The package does not exist on genesis yet — this is a fresh build. No prior source, no test results, no coverage data. The old enterprise-browser-audio-engine openspec was browser-only and did not include beat detection.


Available workspace deps on genesis

Package Role
@suaveplan/audio-core (workspace:^) AudioDocument, BlockProcessor, BlockContext
@suaveplan/error (workspace:^) AudioError base class; AUDIO_ANALYSIS.* codes
@suaveplan/types (workspace:^) LoggerLike
@suaveplan/opentelemetry (workspace:^) OTel spans, counters, histograms
zod (catalog:forms) Zod schemas for option types

Dev deps: vitest, @vitest/coverage-istanbul, fast-check, mitata (all catalog:testing).


Public API

Core types

interface BeatDetectorOptions {
  minBpm?: number        // default 60
  maxBpm?: number        // default 200
  algorithm?: 'energy' | 'spectral-flux' | 'comb'  // default 'energy'
}

interface BeatResult extends AnalysisResult {
  bpm: number
  beats: Float64Array    // beat timestamps (seconds)
  onsets: Float64Array   // onset timestamps (seconds)
  confidence: number     // 0..1
}

class BeatDetector implements AnalysisOp {
  readonly name = 'beat-detector'
  readonly description = 'Detect tempo and beat locations'
  
  constructor(options?: BeatDetectorOptions)
  
  analyze(doc: AudioDocument, opts?: BeatDetectorOptions): Promise<BeatResult>
  analyzeStream(doc: AudioDocument, opts?: BeatDetectorOptions): AsyncGenerator<BeatResult>
  analyzeBlock(block: Float32Array[], ctx: BlockContext): BeatResult
}

Error codes

type BEATErrorCode =
  | 'AUDIO_ANALYSIS_BEAT.INVALID_OPTIONS'
  | 'AUDIO_ANALYSIS_BEAT.EMPTY_DOCUMENT'
  | 'AUDIO_ANALYSIS_BEAT.NO_BEATS_DETECTED'

const AUDIO_ANALYSIS_BEAT_ERROR_METADATA: Readonly<Record<BEATErrorCode, CodeMetadata>>
function registerAudioAnalysisErrorCodes(): void

Zod schemas

BeatDetectorOptionsSchema
BeatResultSchema

New additions for genesis

  1. Three algorithms — energy ODF (fast, from existing block stats), spectral flux (FFT-based, higher precision), comb-filter tempo estimation.
  2. Beat grid alignment — phase-align detected onsets to a regular grid after tempo is known.
  3. Streaming refinement — analyzeStream() yields partial results that refine as more audio is processed.
  4. Block-level real-time — analyzeBlock() returns instantaneous onset detection for visualization.
  5. OTel instrumentation — span audio.analysis.beat, counter audio.analysis.beat.runs_total, histogram audio.analysis.beat.duration_ms.
  6. Property-based tests — synthetic metronome input yields exact BPM, silence yields no beats with graceful fallback.
  7. Benchmark suite — analyze 1-minute track, analyze 10-minute track.

File layout

packages/media/audio/audio-analysis-beat/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    error-codes.ts
    detector/
      beat-detector.ts
      beat-detector.md
      beat-detector.types.ts
      beat-detector.test.ts
      index.ts
    algorithms/
      energy-odf.ts
      energy-odf.md
      energy-odf.test.ts
      spectral-flux.ts
      spectral-flux.md
      spectral-flux.test.ts
      comb-tempo.ts
      comb-tempo.md
      comb-tempo.test.ts
      beat-grid.ts
      beat-grid.md
      beat-grid.test.ts
      index.ts
    __benchmarks__/
      beat.bench.ts
  tests/
    integration.test.ts
    property.test.ts

Impact

Breaking changes: none — fresh build, package does not yet exist on genesis.

Prerequisites: @suaveplan/audio-core, @suaveplan/error, @suaveplan/types, @suaveplan/opentelemetry published to Verdaccio. All four already exist on genesis.

Affected dependents

No dependents in this batch (verified by bunx turbo ls --filter=...@suaveplan/audio-analysis-beat). @suaveplan/audio-analysis-beat is a leaf Analysis Op plugin — no other package in this 13-change audio batch depends on it. It is consumed at runtime by application/timeline code that registers it as a sidecar analysis op (e.g. auto-mixing in @suaveplan/audio-plugins-fx, visualisation in a future react-audio-player, batch analysis in @suaveplan/audio-cli) — those consumers depend on @suaveplan/audio-core's AnalysisOp interface, not on this package directly, and none are created or modified by this change.