# 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 ```ts 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 analyzeStream(doc: AudioDocument, opts?: BeatDetectorOptions): AsyncGenerator analyzeBlock(block: Float32Array[], ctx: BlockContext): BeatResult } ``` ### Error codes ```ts 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> function registerAudioAnalysisErrorCodes(): void ``` ### Zod schemas ```ts 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 ```text 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.