@octoseq/mir 0.1.0-main.4ecb074 → 0.1.0-main.5fdb072
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/dist/chunk-HF3QHCRK.js +3234 -0
- package/dist/chunk-HF3QHCRK.js.map +1 -0
- package/dist/index.d.ts +2122 -47
- package/dist/index.js +3524 -39
- package/dist/index.js.map +1 -1
- package/dist/runMir-CnJQbBr8.d.ts +187 -0
- package/dist/runner/runMir.d.ts +2 -2
- package/dist/runner/runMir.js +1 -1
- package/dist/runner/workerProtocol.d.ts +8 -1
- package/dist/runner/workerProtocol.js.map +1 -1
- package/dist/types-DqH4umN8.d.ts +761 -0
- package/package.json +2 -2
- package/src/dsp/activity.ts +544 -0
- package/src/dsp/bandCqt.ts +662 -0
- package/src/dsp/bandEvents.ts +351 -0
- package/src/dsp/bandMask.ts +225 -0
- package/src/dsp/bandMir.ts +524 -0
- package/src/dsp/bandProposal.ts +552 -0
- package/src/dsp/beatCandidates.ts +299 -0
- package/src/dsp/cqt.ts +386 -0
- package/src/dsp/cqtSignals.ts +462 -0
- package/src/dsp/customSignalReduction.ts +841 -0
- package/src/dsp/eventToSignal.ts +531 -0
- package/src/dsp/frequencyBand.ts +956 -0
- package/src/dsp/mel.ts +56 -3
- package/src/dsp/musicalTime.ts +240 -0
- package/src/dsp/onset.ts +296 -30
- package/src/dsp/peakPicking.ts +519 -0
- package/src/dsp/phaseAlignment.ts +153 -0
- package/src/dsp/pitch.ts +289 -0
- package/src/dsp/resample.ts +44 -0
- package/src/dsp/signalTransforms.ts +660 -0
- package/src/dsp/silenceGating.ts +511 -0
- package/src/dsp/spectral.ts +124 -4
- package/src/dsp/tempoHypotheses.ts +395 -0
- package/src/gpu/bufferPool.ts +266 -0
- package/src/gpu/context.ts +30 -6
- package/src/gpu/helpers.ts +85 -0
- package/src/gpu/melProject.ts +83 -0
- package/src/index.ts +366 -5
- package/src/runner/runMir.ts +234 -2
- package/src/runner/workerProtocol.ts +9 -1
- package/src/types.ts +768 -3
- package/dist/chunk-DUWYCAVG.js +0 -1525
- package/dist/chunk-DUWYCAVG.js.map +0 -1
- package/dist/runMir-CSIBwNZ3.d.ts +0 -84
- package/dist/types-BE3py4fZ.d.ts +0 -83
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { G as MirAudioPayload, E as MirRunRequest, A as MirResult } from './types-DqH4umN8.js';
|
|
2
|
+
|
|
3
|
+
interface BufferPoolStats {
|
|
4
|
+
totalBuffers: number;
|
|
5
|
+
activeBuffers: number;
|
|
6
|
+
availableBuffers: number;
|
|
7
|
+
poolsByUsage: Map<number, number>;
|
|
8
|
+
totalMemoryBytes: number;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Buffer pool configuration options.
|
|
12
|
+
*/
|
|
13
|
+
interface BufferPoolOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Maximum number of buffers to keep in the pool per usage type.
|
|
16
|
+
* Default: 32
|
|
17
|
+
*/
|
|
18
|
+
maxBuffersPerUsage?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Time in milliseconds before an unused buffer is destroyed.
|
|
21
|
+
* Default: 60000 (1 minute)
|
|
22
|
+
*/
|
|
23
|
+
bufferTTLMs?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Whether to enable automatic cleanup of old buffers.
|
|
26
|
+
* Default: true
|
|
27
|
+
*/
|
|
28
|
+
enableAutoCleanup?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Interval in milliseconds for automatic cleanup.
|
|
31
|
+
* Default: 30000 (30 seconds)
|
|
32
|
+
*/
|
|
33
|
+
cleanupIntervalMs?: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* BufferPool manages reusable GPU buffers to reduce allocation overhead.
|
|
37
|
+
*
|
|
38
|
+
* Usage:
|
|
39
|
+
* ```ts
|
|
40
|
+
* const pool = new BufferPool(gpu.device);
|
|
41
|
+
* const buffer = pool.acquire(1024, GPUBufferUsage.STORAGE);
|
|
42
|
+
* // ... use buffer ...
|
|
43
|
+
* pool.release(buffer);
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
declare class BufferPool {
|
|
47
|
+
private device;
|
|
48
|
+
private options;
|
|
49
|
+
private availableBuffers;
|
|
50
|
+
private activeBuffers;
|
|
51
|
+
private cleanupInterval;
|
|
52
|
+
constructor(device: GPUDevice, options?: BufferPoolOptions);
|
|
53
|
+
/**
|
|
54
|
+
* Acquire a buffer from the pool or create a new one if none available.
|
|
55
|
+
*
|
|
56
|
+
* @param size - Byte size of the buffer
|
|
57
|
+
* @param usage - Buffer usage flags (e.g. GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST)
|
|
58
|
+
* @returns A GPUBuffer ready for use
|
|
59
|
+
*/
|
|
60
|
+
acquire(size: number, usage: number): GPUBuffer;
|
|
61
|
+
/**
|
|
62
|
+
* Release a buffer back to the pool for reuse.
|
|
63
|
+
*
|
|
64
|
+
* @param buffer - The buffer to release
|
|
65
|
+
* @param size - Original size of the buffer
|
|
66
|
+
* @param usage - Original usage flags of the buffer
|
|
67
|
+
*/
|
|
68
|
+
release(buffer: GPUBuffer, size: number, usage: number): void;
|
|
69
|
+
/**
|
|
70
|
+
* Clean up old unused buffers that exceed the TTL.
|
|
71
|
+
*/
|
|
72
|
+
cleanup(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Destroy all pooled buffers and clear the pool.
|
|
75
|
+
*/
|
|
76
|
+
clear(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Get statistics about the buffer pool.
|
|
79
|
+
*/
|
|
80
|
+
getStats(): BufferPoolStats;
|
|
81
|
+
/**
|
|
82
|
+
* Start automatic cleanup of old buffers.
|
|
83
|
+
*/
|
|
84
|
+
private startAutoCleanup;
|
|
85
|
+
/**
|
|
86
|
+
* Stop automatic cleanup.
|
|
87
|
+
*/
|
|
88
|
+
stopAutoCleanup(): void;
|
|
89
|
+
/**
|
|
90
|
+
* Dispose of the buffer pool and destroy all buffers.
|
|
91
|
+
*/
|
|
92
|
+
dispose(): void;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* WebGPU context wrapper for MIR computations.
|
|
97
|
+
*
|
|
98
|
+
* Includes buffer pooling for efficient GPU memory reuse across operations.
|
|
99
|
+
*/
|
|
100
|
+
declare class MirGPU {
|
|
101
|
+
readonly device: GPUDevice;
|
|
102
|
+
readonly queue: GPUQueue;
|
|
103
|
+
readonly bufferPool: BufferPool;
|
|
104
|
+
private constructor();
|
|
105
|
+
static create(bufferPoolOptions?: BufferPoolOptions): Promise<MirGPU>;
|
|
106
|
+
/**
|
|
107
|
+
* Get statistics about buffer pool usage.
|
|
108
|
+
*/
|
|
109
|
+
getBufferPoolStats(): BufferPoolStats;
|
|
110
|
+
/**
|
|
111
|
+
* Manually trigger buffer pool cleanup (normally runs automatically).
|
|
112
|
+
*/
|
|
113
|
+
cleanupBufferPool(): void;
|
|
114
|
+
/**
|
|
115
|
+
* Dispose of the GPU context and clean up all resources.
|
|
116
|
+
*/
|
|
117
|
+
dispose(): void;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
type AudioBufferLike = {
|
|
121
|
+
sampleRate: number;
|
|
122
|
+
getChannelData(channel: number): Float32Array;
|
|
123
|
+
numberOfChannels: number;
|
|
124
|
+
};
|
|
125
|
+
type SpectrogramConfig = {
|
|
126
|
+
fftSize: number;
|
|
127
|
+
hopSize: number;
|
|
128
|
+
window: "hann";
|
|
129
|
+
};
|
|
130
|
+
type SpectrogramOptions = {
|
|
131
|
+
/** Optional cancellation hook; checked once per frame. */
|
|
132
|
+
isCancelled?: () => boolean;
|
|
133
|
+
};
|
|
134
|
+
type Spectrogram = {
|
|
135
|
+
sampleRate: number;
|
|
136
|
+
fftSize: number;
|
|
137
|
+
hopSize: number;
|
|
138
|
+
times: Float32Array;
|
|
139
|
+
magnitudes: Float32Array[];
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Compute a magnitude spectrogram.
|
|
143
|
+
*
|
|
144
|
+
* v0.1 implementation:
|
|
145
|
+
* - CPU STFT + FFT for correctness.
|
|
146
|
+
* - The function accepts an optional MirGPU to match the future API.
|
|
147
|
+
* (STFT/FFT is the largest dense math block and can be ported to WebGPU later.)
|
|
148
|
+
*/
|
|
149
|
+
declare function spectrogram(audio: AudioBufferLike, config: SpectrogramConfig, gpu?: MirGPU, options?: SpectrogramOptions): Promise<Spectrogram>;
|
|
150
|
+
|
|
151
|
+
type RunMirOptions = {
|
|
152
|
+
gpu?: MirGPU;
|
|
153
|
+
/** If provided, long loops should periodically call this and abort if true. */
|
|
154
|
+
isCancelled?: () => boolean;
|
|
155
|
+
/** If true and backend==='gpu', do not silently fall back to CPU on GPU errors. */
|
|
156
|
+
strictGpu?: boolean;
|
|
157
|
+
onset?: {
|
|
158
|
+
smoothMs?: number;
|
|
159
|
+
diffMethod?: "rectified" | "abs";
|
|
160
|
+
useLog?: boolean;
|
|
161
|
+
};
|
|
162
|
+
peakPick?: {
|
|
163
|
+
minIntervalSec?: number;
|
|
164
|
+
threshold?: number;
|
|
165
|
+
adaptiveFactor?: number;
|
|
166
|
+
};
|
|
167
|
+
hpss?: {
|
|
168
|
+
timeMedian?: number;
|
|
169
|
+
freqMedian?: number;
|
|
170
|
+
spectrogram?: SpectrogramConfig;
|
|
171
|
+
};
|
|
172
|
+
mfcc?: {
|
|
173
|
+
nCoeffs?: number;
|
|
174
|
+
spectrogram?: SpectrogramConfig;
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
type RunMirBackendOptions = RunMirOptions;
|
|
178
|
+
/**
|
|
179
|
+
* Shared MIR execution entrypoint used by the main thread and by the worker.
|
|
180
|
+
*
|
|
181
|
+
* Notes:
|
|
182
|
+
* - We keep FFT/STFT on CPU for now (spectrogram()), but allow one downstream stage
|
|
183
|
+
* (mel projection) to run on real WebGPU via `melSpectrogram(spec, config, gpu)`.
|
|
184
|
+
*/
|
|
185
|
+
declare function runMir(audio: MirAudioPayload, request: MirRunRequest, options?: RunMirOptions): Promise<MirResult>;
|
|
186
|
+
|
|
187
|
+
export { type AudioBufferLike as A, MirGPU as M, type RunMirOptions as R, type Spectrogram as S, type SpectrogramConfig as a, type RunMirBackendOptions as b, runMir as r, spectrogram as s };
|
package/dist/runner/runMir.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { b as RunMirBackendOptions, R as RunMirOptions, r as runMir } from '../runMir-
|
|
2
|
-
import '../types-
|
|
1
|
+
export { b as RunMirBackendOptions, R as RunMirOptions, r as runMir } from '../runMir-CnJQbBr8.js';
|
|
2
|
+
import '../types-DqH4umN8.js';
|
package/dist/runner/runMir.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { E as MirRunRequest, A as MirResult, B as BeatCandidate, T as TempoHypothesis, G as MirAudioPayload } from '../types-DqH4umN8.js';
|
|
2
2
|
|
|
3
3
|
type MirWorkerInitMessage = {
|
|
4
4
|
type: "INIT";
|
|
@@ -85,6 +85,13 @@ type MirWorkerResultMessage = {
|
|
|
85
85
|
strength: number;
|
|
86
86
|
index: number;
|
|
87
87
|
}>;
|
|
88
|
+
candidates?: BeatCandidate[];
|
|
89
|
+
hypotheses?: TempoHypothesis[];
|
|
90
|
+
inputCandidateCount?: number;
|
|
91
|
+
histogram?: {
|
|
92
|
+
bpmBins: ArrayBufferLike;
|
|
93
|
+
counts: ArrayBufferLike;
|
|
94
|
+
};
|
|
88
95
|
meta: MirResult["meta"];
|
|
89
96
|
};
|
|
90
97
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runner/workerProtocol.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"sources":["../../src/runner/workerProtocol.ts"],"names":[],"mappings":";AA+LO,SAAS,oBAAoB,CAAA,EAAkD;AAClF,EAAA,OAAO;AAAA,IACH,YAAY,CAAA,CAAE,UAAA;AAAA,IACd,IAAA,EAAM,IAAI,YAAA,CAAa,CAAA,CAAE,IAAmB;AAAA,GAChD;AACJ","file":"workerProtocol.js","sourcesContent":["import type { BeatCandidate, MirAudioPayload, MirResult, MirRunRequest, TempoHypothesis } from \"../types\";\n\nexport type MirWorkerInitMessage = {\n type: \"INIT\";\n enableGpu: boolean;\n};\n\nexport type MirWorkerRunMessage = {\n type: \"RUN\";\n jobId: string;\n request: MirRunRequest;\n audio: {\n sampleRate: number;\n mono: ArrayBufferLike; // transferred\n };\n enableGpu: boolean;\n strictGpu?: boolean;\n};\n\nexport type MirWorkerCancelMessage = {\n type: \"CANCEL\";\n jobId: string;\n};\n\nexport type MirWorkerSearchMessage = {\n type: \"SEARCH\";\n jobId: string;\n\n audio: {\n sampleRate: number;\n mono: ArrayBufferLike; // transferred\n };\n\n query: {\n t0: number;\n t1: number;\n };\n\n /** Search tuning (kept small and explicit, like MirRunRequest). */\n search?: {\n hopSec?: number;\n threshold?: number;\n /** 0..1; if true, skip windows overlapping the query itself. */\n skipOverlap?: boolean;\n weights?: {\n mel?: number;\n transient?: number;\n mfcc?: number;\n };\n /** Optional: apply softmax to similarity curve before returning. */\n applySoftmax?: boolean;\n };\n\n /** Feature extraction config (re-uses existing MIR request knobs). */\n features?: {\n spectrogram?: MirRunRequest[\"spectrogram\"];\n mel?: MirRunRequest[\"mel\"];\n onset?: MirRunRequest[\"onset\"];\n mfcc?: MirRunRequest[\"mfcc\"];\n };\n\n /**\n * Optional human-in-the-loop refinement data.\n * When enabled, the worker can use accepted/rejected exemplars to produce a\n * per-track confidence curve and a re-ranked candidate list.\n */\n refinement?: {\n enabled?: boolean;\n includeQueryAsPositive?: boolean;\n labels?: Array<{\n t0: number;\n t1: number;\n status: \"accepted\" | \"rejected\";\n source: \"auto\" | \"manual\";\n }>;\n };\n\n enableGpu: boolean;\n strictGpu?: boolean;\n};\n\nexport type MirWorkerInMessage = MirWorkerInitMessage | MirWorkerRunMessage | MirWorkerSearchMessage | MirWorkerCancelMessage;\n\nexport type MirWorkerResultMessage = {\n type: \"RESULT\";\n jobId: string;\n /** Total time spent in the worker handling this RUN, including (optional) GPU readback. */\n workerTotalMs: number;\n result: {\n // Mirror MirResult but transfer underlying buffers.\n kind: MirResult[\"kind\"];\n times: ArrayBufferLike;\n values?: ArrayBufferLike;\n data2d?: ArrayBufferLike[];\n events?: Array<{ time: number; strength: number; index: number }>;\n candidates?: BeatCandidate[];\n // For tempoHypotheses\n hypotheses?: TempoHypothesis[];\n inputCandidateCount?: number;\n histogram?: {\n bpmBins: ArrayBufferLike;\n counts: ArrayBufferLike;\n };\n meta: MirResult[\"meta\"];\n };\n};\n\nexport type MirWorkerErrorMessage = {\n type: \"ERROR\";\n jobId: string;\n message: string;\n stack?: string;\n};\n\nexport type MirWorkerLogMessage = {\n type: \"LOG\";\n jobId?: string;\n level: \"debug\" | \"info\" | \"warn\" | \"error\";\n message: string;\n data?: unknown;\n};\n\nexport type MirWorkerSearchResultMessage = {\n type: \"SEARCH_RESULT\";\n jobId: string;\n timings: {\n fingerprintMs: number;\n scanMs: number;\n modelMs?: number;\n totalMs: number;\n };\n result: {\n times: ArrayBufferLike;\n scores: ArrayBufferLike;\n curveKind: \"similarity\" | \"confidence\";\n model: {\n kind: \"baseline\" | \"prototype\" | \"logistic\";\n positives: number;\n negatives: number;\n weightL2?: {\n mel: number;\n melForeground: number;\n melContrast?: number;\n onset: number;\n onsetForeground: number;\n onsetContrast?: number;\n mfcc?: number;\n mfccForeground?: number;\n mfccContrast?: number;\n };\n training?: {\n iterations: number;\n finalLoss: number;\n };\n };\n candidates: Array<{\n timeSec: number;\n score: number;\n windowStartSec: number;\n windowEndSec: number;\n explain?: {\n groupLogit?: {\n logit: number;\n bias: number;\n mel: number;\n melForeground: number;\n melContrast?: number;\n onset: number;\n onsetForeground: number;\n onsetContrast?: number;\n mfcc?: number;\n mfccForeground?: number;\n mfccContrast?: number;\n };\n };\n }>;\n meta: {\n windowSec: number;\n hopSec: number;\n skippedWindows: number;\n scannedWindows: number;\n };\n };\n};\n\nexport type MirWorkerOutMessage =\n | MirWorkerResultMessage\n | MirWorkerSearchResultMessage\n | MirWorkerErrorMessage\n | MirWorkerLogMessage;\n\nexport function rebuildAudioPayload(a: MirWorkerRunMessage[\"audio\"]): MirAudioPayload {\n return {\n sampleRate: a.sampleRate,\n mono: new Float32Array(a.mono as ArrayBuffer),\n };\n}\n"]}
|