@audio/beat 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +25 -0
- package/README.md +336 -0
- package/index.d.ts +68 -0
- package/index.js +12 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Dmitry Iv
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
This work is offered under the Krishnized License (https://github.com/krishnized/license).
|
package/README.md
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# @audio/beat [](https://github.com/audiojs/beat/actions/workflows/test.yml) [](https://www.npmjs.com/package/@audio/beat) [](https://github.com/krishnized/license)
|
|
2
|
+
|
|
3
|
+
Onset detection, tempo estimation, and beat tracking. · **[live demo ↗](https://audiojs.github.io/beat-detection/)**
|
|
4
|
+
|
|
5
|
+
<table><tr><td valign="top">
|
|
6
|
+
|
|
7
|
+
**[Onset Detection](#onset-detection)**<br>
|
|
8
|
+
<sub>[onsets](#onsetsdata-opts) · [energyOnsets](#energyonsetsdata-opts) · [phaseOnsets](#phaseonsetsdata-opts) · [bandOnsets](#bandonsetsdata-opts)</sub>
|
|
9
|
+
|
|
10
|
+
**[Tempo Estimation](#tempo-estimation)**<br>
|
|
11
|
+
<sub>[tempo](#tempodata-opts) · [combTempo](#combtempodata-opts)</sub>
|
|
12
|
+
|
|
13
|
+
</td><td valign="top">
|
|
14
|
+
|
|
15
|
+
**[Beat Tracking](#beat-tracking)**<br>
|
|
16
|
+
<sub>[detect](#detectdata-opts) · [beatTrack](#beattrackdata-opts)</sub>
|
|
17
|
+
|
|
18
|
+
**[Utilities](#utilities)**<br>
|
|
19
|
+
<sub>[spectralFlux](#spectralfluxdata-opts) · [energyFlux](#energyfluxdata-opts) · [peakPick](#peakpickodf-opts)</sub>
|
|
20
|
+
|
|
21
|
+
</td></tr></table>
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
npm install @audio/beat
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
import { detect, onsets, tempo, beatTrack } from '@audio/beat'
|
|
32
|
+
|
|
33
|
+
// full pipeline: onsets → tempo → beat grid
|
|
34
|
+
let result = detect(samples, { fs: 44100 })
|
|
35
|
+
result.bpm // 120.2
|
|
36
|
+
result.beats // Float64Array [0.01, 0.51, 1.01, ...]
|
|
37
|
+
result.onsets // Float64Array [0.01, 0.26, 0.51, ...]
|
|
38
|
+
|
|
39
|
+
// individual algorithms
|
|
40
|
+
let ons = onsets(samples, { fs: 44100 }) // onset times in seconds
|
|
41
|
+
let tmp = tempo(samples, { fs: 44100 }) // { bpm, confidence }
|
|
42
|
+
let bt = beatTrack(samples, { fs: 44100 }) // { beats, bpm, confidence }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
> Works in Node.js and browser. No Web Audio API needed — operates on raw `Float32Array` / `Float64Array` samples.
|
|
46
|
+
>
|
|
47
|
+
> **Mono only.** Pass a single channel. For stereo, use one channel (`buffer.getChannelData(0)`) or mix to mono first.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
## How it works
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
┌──────────────────────────────────────────┐
|
|
54
|
+
│ raw samples │
|
|
55
|
+
└──────────┬───────────────────┬────────────┘
|
|
56
|
+
│ │
|
|
57
|
+
┌──────────▼──────────┐ ┌─────▼──────────┐
|
|
58
|
+
│ Onset Detection │ │ Tempo Estimation│
|
|
59
|
+
│ │ │ │
|
|
60
|
+
│ STFT → magnitude → │ │ autocorrelation│
|
|
61
|
+
│ positive flux → │ │ or comb-filter │
|
|
62
|
+
│ adaptive threshold │ │ of ODF │
|
|
63
|
+
└──────────┬──────────┘ └─────┬──────────┘
|
|
64
|
+
│ │
|
|
65
|
+
│ ┌──────────────┘
|
|
66
|
+
│ │
|
|
67
|
+
┌──────────▼────▼─────────────────────────┐
|
|
68
|
+
│ Beat Tracking │
|
|
69
|
+
│ │
|
|
70
|
+
│ phase-aligned grid (detect) │
|
|
71
|
+
│ or DP optimal sequence (beatTrack) │
|
|
72
|
+
└──────────────────────────────────────────┘
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Onset detection** finds *when* events happen — note attacks, drum hits, transients. Four algorithms with different trade-offs.
|
|
76
|
+
|
|
77
|
+
**Tempo estimation** finds *how fast* — the dominant periodicity in the onset function. Two methods: autocorrelation and comb-filter resonance.
|
|
78
|
+
|
|
79
|
+
**Beat tracking** combines both: given onsets and tempo, find the beat positions. `detect` snaps a grid to onsets; `beatTrack` uses dynamic programming to find the globally optimal beat sequence.
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
## Onset Detection
|
|
83
|
+
|
|
84
|
+
All onset functions take raw samples and return onset times in seconds as `Float64Array`.
|
|
85
|
+
|
|
86
|
+
### `onsets(data, opts)`
|
|
87
|
+
|
|
88
|
+
Spectral flux. STFT → magnitude → sum positive frame-to-frame differences → adaptive threshold peak-pick. The general-purpose default.
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
import { onsets } from '@audio/beat'
|
|
92
|
+
let ons = onsets(samples, { fs: 44100 })
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
| Param | Default | |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| `fs` | `44100` | Sample rate |
|
|
98
|
+
| `frameSize` | `2048` | STFT window size |
|
|
99
|
+
| `hopSize` | `512` | Hop between frames |
|
|
100
|
+
| `delta` | `1.4` | Adaptive threshold multiplier |
|
|
101
|
+
| `windowSize` | `8` | Peak-pick local mean window (frames) |
|
|
102
|
+
|
|
103
|
+
**Use when:** General-purpose onset detection — music, speech, mixed material.<br>
|
|
104
|
+
**Ref:** Dixon, "Onset Detection Revisited" (DAFx 2006).<br>
|
|
105
|
+
**Complexity:** $O(N \log F)$ where $N$ = samples, $F$ = frame size (FFT).
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
### `energyOnsets(data, opts)`
|
|
109
|
+
|
|
110
|
+
Energy flux. Per-frame RMS energy → positive first differences → adaptive threshold. No FFT — fastest algorithm. Best for strong transients.
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
import { energyOnsets } from '@audio/beat'
|
|
114
|
+
let ons = energyOnsets(samples, { fs: 44100 })
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Same params as `onsets`.
|
|
118
|
+
|
|
119
|
+
**Use when:** Percussive material, real-time, CPU-constrained — 10× faster than spectral flux.<br>
|
|
120
|
+
**Not for:** Soft onsets, pitched instruments with gradual attacks.<br>
|
|
121
|
+
**Ref:** Klapuri, "Auditory Model Based Beat Tracking" (ICMC 1999).<br>
|
|
122
|
+
**Complexity:** $O(N)$ — no FFT, just RMS per frame.
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
### `phaseOnsets(data, opts)`
|
|
126
|
+
|
|
127
|
+
Phase deviation. Measures divergence between predicted and actual STFT phase, weighted by magnitude. More robust to steady-state signals (sustained notes, drones) than spectral flux.
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
import { phaseOnsets } from '@audio/beat'
|
|
131
|
+
let ons = phaseOnsets(samples, { fs: 44100 })
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Same params as `onsets`.
|
|
135
|
+
|
|
136
|
+
**Use when:** Material with sustained tones where spectral flux produces false onsets.<br>
|
|
137
|
+
**Not for:** Speed-critical paths — requires complex FFT (2× cost of spectral flux).<br>
|
|
138
|
+
**Ref:** Bello et al., "A Tutorial on Onset Detection in Music Signals" (IEEE TASLP 2005).<br>
|
|
139
|
+
**Complexity:** $O(N \log F)$ with complex FFT.
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
### `bandOnsets(data, opts)`
|
|
143
|
+
|
|
144
|
+
Multi-band spectral flux. Splits spectrum into frequency bands, computes spectral flux per band, sums. Detects onsets across different instrument ranges simultaneously.
|
|
145
|
+
|
|
146
|
+
```js
|
|
147
|
+
import { bandOnsets } from '@audio/beat'
|
|
148
|
+
let ons = bandOnsets(samples, { fs: 44100, bands: 6 })
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
| Param | Default | |
|
|
152
|
+
|---|---|---|
|
|
153
|
+
| `bands` | `4` | Number of frequency bands |
|
|
154
|
+
| + all `onsets` params | | |
|
|
155
|
+
|
|
156
|
+
**Use when:** Full-band music where low-frequency kicks and high-frequency hats produce onsets that a single-band detector misses.<br>
|
|
157
|
+
**Ref:** Klapuri, "Sound Onset Detection by Applying Psychoacoustic Knowledge" (ICASSP 1999).<br>
|
|
158
|
+
**Complexity:** $O(N \log F)$ — same FFT cost, slightly more post-processing.
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
### Onset comparison
|
|
162
|
+
|
|
163
|
+
| | Speed | Transients | Soft onsets | Steady-state | Best for |
|
|
164
|
+
|---|---|---|---|---|---|
|
|
165
|
+
| `onsets` | ★★★ | ★★★★ | ★★★ | ★★ | General purpose |
|
|
166
|
+
| `energyOnsets` | ★★★★★ | ★★★★★ | ★ | ★ | Percussive, real-time |
|
|
167
|
+
| `phaseOnsets` | ★★ | ★★★ | ★★★★ | ★★★★ | Sustained tones |
|
|
168
|
+
| `bandOnsets` | ★★★ | ★★★★ | ★★★ | ★★★ | Full-band music |
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
## Tempo Estimation
|
|
172
|
+
|
|
173
|
+
Both return `{ bpm, confidence }`. Pass `candidates: N` to get ranked alternatives.
|
|
174
|
+
|
|
175
|
+
### `tempo(data, opts)`
|
|
176
|
+
|
|
177
|
+
Autocorrelation of the onset detection function. Finds the dominant periodicity by correlating the spectral flux ODF with itself at different lags. Perceptual weighting (log-Gaussian centered at 120 BPM) resolves octave ambiguity.
|
|
178
|
+
|
|
179
|
+
```js
|
|
180
|
+
import { tempo } from '@audio/beat'
|
|
181
|
+
let { bpm, confidence } = tempo(samples, { fs: 44100 })
|
|
182
|
+
let { bpm, candidates } = tempo(samples, { fs: 44100, candidates: 3 })
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
| Param | Default | |
|
|
186
|
+
|---|---|---|
|
|
187
|
+
| `fs` | `44100` | Sample rate |
|
|
188
|
+
| `minBpm` | `60` | Minimum BPM to consider |
|
|
189
|
+
| `maxBpm` | `200` | Maximum BPM to consider |
|
|
190
|
+
| `candidates` | `1` | Number of tempo candidates to return |
|
|
191
|
+
|
|
192
|
+
**Use when:** General tempo estimation — robust for most material.<br>
|
|
193
|
+
**Ref:** Ellis, "Beat Tracking by Dynamic Programming" (JNMR 2007).<br>
|
|
194
|
+
**Complexity:** $O(N \log F + L^2)$ where $L$ = lag range in ODF frames.
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
### `combTempo(data, opts)`
|
|
198
|
+
|
|
199
|
+
Comb-filter resonance. Tests BPM hypotheses by correlating the ODF with raised-cosine pulse trains at each candidate tempo (+ harmonics). Returns the BPM with highest resonance.
|
|
200
|
+
|
|
201
|
+
```js
|
|
202
|
+
import { combTempo } from '@audio/beat'
|
|
203
|
+
let { bpm, confidence } = combTempo(samples, { fs: 44100 })
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Same params as `tempo`.
|
|
207
|
+
|
|
208
|
+
**Use when:** Cross-validation with autocorrelation, or when the signal has strong harmonic tempo structure.<br>
|
|
209
|
+
**Ref:** Scheirer, "Tempo and Beat Analysis of Acoustic Musical Signals" (JASA 1998).<br>
|
|
210
|
+
**Complexity:** $O(N \log F + B \cdot L)$ where $B$ = BPM range tested.
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
## Beat Tracking
|
|
214
|
+
|
|
215
|
+
### `detect(data, opts)`
|
|
216
|
+
|
|
217
|
+
Full pipeline: spectral flux onsets → comb-filter tempo → phase-aligned beat grid. Shares a single STFT pass across onset and tempo stages, so it costs only marginally more than either alone.
|
|
218
|
+
|
|
219
|
+
```js
|
|
220
|
+
import { detect } from '@audio/beat'
|
|
221
|
+
let { bpm, confidence, beats, onsets } = detect(samples, { fs: 44100 })
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Returns `{ bpm, confidence, beats: Float64Array, onsets: Float64Array }`.
|
|
225
|
+
|
|
226
|
+
**Use when:** Quick one-call solution — good enough for most applications.<br>
|
|
227
|
+
**Not for:** Tempo changes or rubato — the grid is uniform. Use `beatTrack` for adaptive tracking.
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
### `beatTrack(data, opts)`
|
|
231
|
+
|
|
232
|
+
Dynamic programming beat tracker. Estimates tempo (via autocorrelation), then finds the globally optimal beat sequence by maximizing onset strength while penalizing tempo deviation. Each beat position is placed where the onset function is strongest, subject to staying near the expected tempo period.
|
|
233
|
+
|
|
234
|
+
```js
|
|
235
|
+
import { beatTrack } from '@audio/beat'
|
|
236
|
+
let { beats, bpm, confidence } = beatTrack(samples, { fs: 44100 })
|
|
237
|
+
let result = beatTrack(samples, { fs: 44100, bpm: 120 }) // hint tempo
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
| Param | Default | |
|
|
241
|
+
|---|---|---|
|
|
242
|
+
| `bpm` | auto-estimated | Target BPM (auto-estimated if omitted) |
|
|
243
|
+
| `tightness` | `680` | Tempo constraint weight (higher = stricter) |
|
|
244
|
+
| + all `tempo` params | | |
|
|
245
|
+
|
|
246
|
+
Returns `{ beats: Float64Array, bpm, confidence }`.
|
|
247
|
+
|
|
248
|
+
**Use when:** Irregular timing, live performance, rubato — adapts to where beats actually fall.<br>
|
|
249
|
+
**Not for:** Perfectly metronomic material — `detect` is faster and sufficient.<br>
|
|
250
|
+
**Ref:** Ellis, "Beat Tracking by Dynamic Programming" (JNMR 2007).
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
## Utilities
|
|
254
|
+
|
|
255
|
+
Low-level building blocks. Used internally, exported for custom pipelines.
|
|
256
|
+
|
|
257
|
+
### `spectralFlux(data, opts)`
|
|
258
|
+
|
|
259
|
+
STFT → magnitude → sum positive differences. Returns the onset detection function (ODF) as `{ odf, nFrames, hopSize, frameSize, fs }`.
|
|
260
|
+
|
|
261
|
+
```js
|
|
262
|
+
import { spectralFlux } from '@audio/beat'
|
|
263
|
+
let { odf, nFrames, hopSize } = spectralFlux(samples, { fs: 44100 })
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### `energyFlux(data, opts)`
|
|
267
|
+
|
|
268
|
+
Per-frame RMS energy → positive first differences. Returns `{ odf, nFrames, hopSize, frameSize, fs }`.
|
|
269
|
+
|
|
270
|
+
### `peakPick(odf, opts)`
|
|
271
|
+
|
|
272
|
+
Adaptive threshold peak-picker. Local mean × delta → pick peaks above threshold. Returns onset times in seconds.
|
|
273
|
+
|
|
274
|
+
```js
|
|
275
|
+
import { spectralFlux, peakPick } from '@audio/beat'
|
|
276
|
+
let { odf, hopSize, fs } = spectralFlux(samples, { fs: 44100 })
|
|
277
|
+
let onsets = peakPick(odf, { hopSize, fs, delta: 1.5 })
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
## Performance
|
|
282
|
+
|
|
283
|
+
All algorithms run 250–8000× faster than real-time on a single core (16.5s signal, 44.1 kHz, Node.js):
|
|
284
|
+
|
|
285
|
+
| Algorithm | Time | Throughput | Real-time multiple |
|
|
286
|
+
|---|---|---|---|
|
|
287
|
+
| `energyOnsets` | 2 ms | 362 Msamp/s | 8200× RT |
|
|
288
|
+
| `onsets` | 19 ms | 38 Msamp/s | 850× RT |
|
|
289
|
+
| `tempo` | 19 ms | 39 Msamp/s | 890× RT |
|
|
290
|
+
| `bandOnsets` | 21 ms | 35 Msamp/s | 790× RT |
|
|
291
|
+
| `combTempo` | 25 ms | 29 Msamp/s | 660× RT |
|
|
292
|
+
| `detect` | 37 ms | 20 Msamp/s | 450× RT |
|
|
293
|
+
| `beatTrack` | 37 ms | 20 Msamp/s | 450× RT |
|
|
294
|
+
| `phaseOnsets` | 63 ms | 12 Msamp/s | 260× RT |
|
|
295
|
+
|
|
296
|
+
Full 8-algorithm pass on 8.5s audio completes in ~150ms in-browser.
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
## Accuracy
|
|
300
|
+
|
|
301
|
+
Systematic benchmark across 10 musical styles × 10 tempos (70–180 BPM) = 100 cases per method.
|
|
302
|
+
|
|
303
|
+
| Method | Acc1 (%) | Acc2 (%) | MAE (BPM) | Octave errors |
|
|
304
|
+
|---|---|---|---|---|
|
|
305
|
+
| `tempo` | 70 | 87 | 19.5 | 16 |
|
|
306
|
+
| `combTempo` | 87 | 93 | 8.7 | 6 |
|
|
307
|
+
| `detect` | 87 | 93 | 8.7 | 6 |
|
|
308
|
+
| `beatTrack` | 87 | 93 | 8.7 | 6 |
|
|
309
|
+
|
|
310
|
+
`detect`, `beatTrack`, and `combTempo` all share a single STFT pass —
|
|
311
|
+
they're as accurate as each other, and all better than the autocorrelation baseline.
|
|
312
|
+
Use `detect` for uniform grids, `beatTrack` for adaptive (rubato-aware) placement.
|
|
313
|
+
|
|
314
|
+
- **Acc1** — exact accuracy within ±5% of target BPM
|
|
315
|
+
- **Acc2** — octave-tolerant accuracy (accepts half/double tempo within ±5%)
|
|
316
|
+
- **MAE** — mean absolute BPM error across all cases
|
|
317
|
+
- **Octave errors** — cases correct at octave level but wrong metrical level
|
|
318
|
+
|
|
319
|
+
> `tempo` (autocorrelation) varies ±2% between runs due to random noise in the FM synth. Comb-filter methods are stable.
|
|
320
|
+
|
|
321
|
+
### Methodology
|
|
322
|
+
|
|
323
|
+
Fully self-contained: FM-synthesis drum patterns (`synth.js`) generate deterministic test signals across 10 styles × 10 BPMs. No external audio files. Also tests against a deterministic [floatbeat](https://dollchan.net/bytebeat/) track (125 BPM). Run `node test.js` to reproduce.
|
|
324
|
+
|
|
325
|
+
### Known limitations
|
|
326
|
+
|
|
327
|
+
- **Syncopated music** (reggae, funk, breakbeat) is hardest — offbeat patterns create strong sub-beat autocorrelation that can double the detected tempo. Octave correction mitigates this for most cases.
|
|
328
|
+
- **Extreme tempos** (<70 or >180 BPM) are outside the default `minBpm`/`maxBpm` range.
|
|
329
|
+
- **Synthetic vs. real audio** — these benchmarks use FM-synthesized patterns, which are cleaner than real recordings. Real-world accuracy may differ due to mix complexity, recording artifacts, and tempo rubato.
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
## See also
|
|
333
|
+
|
|
334
|
+
- [digital-filter](https://github.com/audiojs/digital-filter) — filter design and processing
|
|
335
|
+
- [stretch](https://github.com/audiojs/stretch) — time stretching and pitch shifting
|
|
336
|
+
- [audio-lena](https://github.com/audiojs/audio-lena) — test audio sample
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export interface OnsetOpts {
|
|
2
|
+
fs?: number
|
|
3
|
+
frameSize?: number
|
|
4
|
+
hopSize?: number
|
|
5
|
+
delta?: number
|
|
6
|
+
windowSize?: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface BandOnsetOpts extends OnsetOpts {
|
|
10
|
+
bands?: number
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface TempoResult {
|
|
14
|
+
bpm: number
|
|
15
|
+
confidence: number
|
|
16
|
+
candidates?: TempoResult[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface TempoOpts {
|
|
20
|
+
fs?: number
|
|
21
|
+
frameSize?: number
|
|
22
|
+
hopSize?: number
|
|
23
|
+
minBpm?: number
|
|
24
|
+
maxBpm?: number
|
|
25
|
+
candidates?: number
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface DetectResult {
|
|
29
|
+
bpm: number
|
|
30
|
+
confidence: number
|
|
31
|
+
beats: Float64Array
|
|
32
|
+
onsets: Float64Array
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface BeatTrackResult {
|
|
36
|
+
beats: Float64Array
|
|
37
|
+
bpm: number
|
|
38
|
+
confidence: number
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface BeatTrackOpts extends TempoOpts {
|
|
42
|
+
bpm?: number
|
|
43
|
+
tightness?: number
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Symbol key for passing a pre-computed ODF result to tempo/track functions, avoiding a second STFT pass. */
|
|
47
|
+
export declare const ODF: unique symbol
|
|
48
|
+
|
|
49
|
+
export declare function detect(data: Float32Array | Float64Array, opts?: OnsetOpts & TempoOpts): DetectResult
|
|
50
|
+
export declare function onsets(data: Float32Array | Float64Array, opts?: OnsetOpts): Float64Array
|
|
51
|
+
export declare function energyOnsets(data: Float32Array | Float64Array, opts?: OnsetOpts): Float64Array
|
|
52
|
+
export declare function phaseOnsets(data: Float32Array | Float64Array, opts?: OnsetOpts): Float64Array
|
|
53
|
+
export declare function bandOnsets(data: Float32Array | Float64Array, opts?: BandOnsetOpts): Float64Array
|
|
54
|
+
export declare function tempo(data: Float32Array | Float64Array | null, opts?: TempoOpts): TempoResult
|
|
55
|
+
export declare function combTempo(data: Float32Array | Float64Array | null, opts?: TempoOpts): TempoResult
|
|
56
|
+
export declare function beatTrack(data: Float32Array | Float64Array, opts?: BeatTrackOpts): BeatTrackResult
|
|
57
|
+
export declare function peakPick(odf: Float64Array, opts?: OnsetOpts): Float64Array
|
|
58
|
+
|
|
59
|
+
export interface FluxResult {
|
|
60
|
+
odf: Float64Array
|
|
61
|
+
nFrames: number
|
|
62
|
+
hopSize: number
|
|
63
|
+
frameSize: number
|
|
64
|
+
fs: number
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export declare function spectralFlux(data: Float32Array | Float64Array, opts?: OnsetOpts): FluxResult
|
|
68
|
+
export declare function energyFlux(data: Float32Array | Float64Array, opts?: OnsetOpts): FluxResult
|
package/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// @audio/beat — beat detection umbrella re-exporting every @audio/beat-* atom.
|
|
2
|
+
// For smaller bundles, depend directly on the individual atom.
|
|
3
|
+
|
|
4
|
+
export { default as detect } from '@audio/beat-detect'
|
|
5
|
+
export { default as onsets } from '@audio/beat-onset'
|
|
6
|
+
export { default as energyOnsets } from '@audio/beat-onset/energy'
|
|
7
|
+
export { default as phaseOnsets } from '@audio/beat-onset/phase'
|
|
8
|
+
export { default as bandOnsets } from '@audio/beat-onset/band'
|
|
9
|
+
export { default as tempo } from '@audio/beat-tempo'
|
|
10
|
+
export { default as combTempo } from '@audio/beat-tempo/comb'
|
|
11
|
+
export { default as beatTrack } from '@audio/beat-track'
|
|
12
|
+
export { spectralFlux, energyFlux, peakPick, ODF } from '@audio/beat-core'
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@audio/beat",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Beat detection — umbrella for @audio/beat-* atoms (onset detection, tempo estimation, beat tracking)",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./index.d.ts",
|
|
9
|
+
"default": "./index.js"
|
|
10
|
+
},
|
|
11
|
+
"./package.json": "./package.json"
|
|
12
|
+
},
|
|
13
|
+
"types": "./index.d.ts",
|
|
14
|
+
"files": [
|
|
15
|
+
"index.js",
|
|
16
|
+
"index.d.ts"
|
|
17
|
+
],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"scripts": {
|
|
20
|
+
"test": "node test.js",
|
|
21
|
+
"test:all": "npm test --workspaces --if-present && npm test",
|
|
22
|
+
"publish:all": "npm publish --workspaces && npm publish"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/audiojs/beat.git"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"beat",
|
|
30
|
+
"beat-detection",
|
|
31
|
+
"bpm",
|
|
32
|
+
"tempo",
|
|
33
|
+
"onset",
|
|
34
|
+
"onset-detection",
|
|
35
|
+
"rhythm",
|
|
36
|
+
"audio",
|
|
37
|
+
"dsp",
|
|
38
|
+
"signal-processing",
|
|
39
|
+
"music"
|
|
40
|
+
],
|
|
41
|
+
"author": "Dmitry Iv. <dfcreative@gmail.com>",
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/audiojs/beat/issues"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/audiojs/beat#readme",
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@audio/beat-core": "^1.0.0",
|
|
52
|
+
"@audio/beat-onset": "^1.0.0",
|
|
53
|
+
"@audio/beat-tempo": "^1.0.0",
|
|
54
|
+
"@audio/beat-detect": "^1.0.0",
|
|
55
|
+
"@audio/beat-track": "^1.0.0"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"audio-decode": "^3.9.0",
|
|
59
|
+
"tst": "^9.4.0"
|
|
60
|
+
},
|
|
61
|
+
"publishConfig": {
|
|
62
|
+
"access": "public"
|
|
63
|
+
},
|
|
64
|
+
"main": "index.js",
|
|
65
|
+
"workspaces": [
|
|
66
|
+
"packages/*"
|
|
67
|
+
]
|
|
68
|
+
}
|