@octoseq/mir 0.1.0-main.0d2814e
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-DUWYCAVG.js +1525 -0
- package/dist/chunk-DUWYCAVG.js.map +1 -0
- package/dist/index.d.ts +450 -0
- package/dist/index.js +1234 -0
- package/dist/index.js.map +1 -0
- package/dist/runMir-CSIBwNZ3.d.ts +84 -0
- package/dist/runner/runMir.d.ts +2 -0
- package/dist/runner/runMir.js +3 -0
- package/dist/runner/runMir.js.map +1 -0
- package/dist/runner/workerProtocol.d.ts +169 -0
- package/dist/runner/workerProtocol.js +11 -0
- package/dist/runner/workerProtocol.js.map +1 -0
- package/dist/types-BE3py4fZ.d.ts +83 -0
- package/package.json +55 -0
- package/src/dsp/fft.ts +22 -0
- package/src/dsp/fftBackend.ts +53 -0
- package/src/dsp/fftBackendFftjs.ts +60 -0
- package/src/dsp/hpss.ts +152 -0
- package/src/dsp/hpssGpu.ts +101 -0
- package/src/dsp/mel.ts +219 -0
- package/src/dsp/mfcc.ts +119 -0
- package/src/dsp/onset.ts +205 -0
- package/src/dsp/peakPick.ts +112 -0
- package/src/dsp/spectral.ts +95 -0
- package/src/dsp/spectrogram.ts +176 -0
- package/src/gpu/README.md +34 -0
- package/src/gpu/context.ts +44 -0
- package/src/gpu/helpers.ts +87 -0
- package/src/gpu/hpssMasks.ts +116 -0
- package/src/gpu/kernels/hpssMasks.wgsl.ts +137 -0
- package/src/gpu/kernels/melProject.wgsl.ts +48 -0
- package/src/gpu/kernels/onsetEnvelope.wgsl.ts +56 -0
- package/src/gpu/melProject.ts +98 -0
- package/src/gpu/onsetEnvelope.ts +81 -0
- package/src/gpu/webgpu.d.ts +176 -0
- package/src/index.ts +121 -0
- package/src/runner/runMir.ts +431 -0
- package/src/runner/workerProtocol.ts +189 -0
- package/src/search/featureVectorV1.ts +123 -0
- package/src/search/fingerprintV1.ts +230 -0
- package/src/search/refinedModelV1.ts +321 -0
- package/src/search/searchTrackV1.ts +206 -0
- package/src/search/searchTrackV1Guided.ts +863 -0
- package/src/search/similarity.ts +98 -0
- package/src/types.ts +105 -0
- package/src/util/display.ts +80 -0
- package/src/util/normalise.ts +58 -0
- package/src/util/stats.ts +25 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WGSL kernel: mel filterbank projection.
|
|
3
|
+
*
|
|
4
|
+
* Computes per-frame mel band energies:
|
|
5
|
+
* out[frame, mel] = log10(eps + sum_k mags[frame, k] * filters[mel, k])
|
|
6
|
+
*
|
|
7
|
+
* Notes:
|
|
8
|
+
* - FFT/STFT stays on CPU (spectrogram()). This kernel only accelerates the dense projection.
|
|
9
|
+
* - Numerical differences vs CPU are expected to be small (floating point order-of-ops).
|
|
10
|
+
*/
|
|
11
|
+
export const melProjectWGSL = /* wgsl */ `
|
|
12
|
+
struct Params {
|
|
13
|
+
nBins: u32,
|
|
14
|
+
nMels: u32,
|
|
15
|
+
nFrames: u32,
|
|
16
|
+
_pad: u32,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
@group(0) @binding(0) var<storage, read> mags : array<f32>;
|
|
20
|
+
@group(0) @binding(1) var<storage, read> filters : array<f32>;
|
|
21
|
+
@group(0) @binding(2) var<storage, read_write> out : array<f32>;
|
|
22
|
+
@group(0) @binding(3) var<uniform> params : Params;
|
|
23
|
+
|
|
24
|
+
fn log10(x: f32) -> f32 {
|
|
25
|
+
return log(x) / log(10.0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@compute @workgroup_size(16, 16)
|
|
29
|
+
fn main(@builtin(global_invocation_id) gid : vec3<u32>) {
|
|
30
|
+
let frame = gid.x;
|
|
31
|
+
let mel = gid.y;
|
|
32
|
+
if (frame >= params.nFrames || mel >= params.nMels) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
var sum: f32 = 0.0;
|
|
37
|
+
let bins = params.nBins;
|
|
38
|
+
let magBase = frame * bins;
|
|
39
|
+
let filBase = mel * bins;
|
|
40
|
+
|
|
41
|
+
for (var k: u32 = 0u; k < bins; k = k + 1u) {
|
|
42
|
+
sum = sum + mags[magBase + k] * filters[filBase + k];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let eps: f32 = 1e-12;
|
|
46
|
+
out[frame * params.nMels + mel] = log10(eps + sum);
|
|
47
|
+
}
|
|
48
|
+
`;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export const onsetEnvelopeWGSL = /* wgsl */ `
|
|
2
|
+
// Compute onset strength envelope from a (log) mel spectrogram.
|
|
3
|
+
//
|
|
4
|
+
// Input layout: melFlat[t*nMels + m]
|
|
5
|
+
// Output layout: out[t]
|
|
6
|
+
//
|
|
7
|
+
// We compute novelty per frame:
|
|
8
|
+
// novelty[t] = sum_m max(0, mel[t,m] - mel[t-1,m]) (rectified)
|
|
9
|
+
// or sum_m abs(...)
|
|
10
|
+
//
|
|
11
|
+
// One invocation computes one frame index (t). This is memory-bound but reduces a full
|
|
12
|
+
// (frames*mels) loop to the GPU and provides an end-to-end submit->readback timing.
|
|
13
|
+
|
|
14
|
+
struct Params {
|
|
15
|
+
nMels: u32,
|
|
16
|
+
nFrames: u32,
|
|
17
|
+
diffMethod: u32, // 0=rectified, 1=abs
|
|
18
|
+
_pad: u32,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
@group(0) @binding(0) var<storage, read> melFlat: array<f32>;
|
|
22
|
+
@group(0) @binding(1) var<storage, read_write> out: array<f32>;
|
|
23
|
+
@group(0) @binding(2) var<uniform> params: Params;
|
|
24
|
+
|
|
25
|
+
@compute @workgroup_size(256)
|
|
26
|
+
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
27
|
+
let t = gid.x;
|
|
28
|
+
if (t >= params.nFrames) { return; }
|
|
29
|
+
|
|
30
|
+
if (t == 0u) {
|
|
31
|
+
out[t] = 0.0;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let nMels = params.nMels;
|
|
36
|
+
var sum: f32 = 0.0;
|
|
37
|
+
|
|
38
|
+
// Linear loop: nMels is small (e.g. 64). Keeping it serial per-frame is fine.
|
|
39
|
+
// (Future optimisation: parallelise reduction within workgroup.)
|
|
40
|
+
for (var m: u32 = 0u; m < nMels; m = m + 1u) {
|
|
41
|
+
let a = melFlat[t * nMels + m];
|
|
42
|
+
let b = melFlat[(t - 1u) * nMels + m];
|
|
43
|
+
let d = a - b;
|
|
44
|
+
|
|
45
|
+
if (params.diffMethod == 1u) {
|
|
46
|
+
// abs
|
|
47
|
+
sum = sum + abs(d);
|
|
48
|
+
} else {
|
|
49
|
+
// rectified
|
|
50
|
+
sum = sum + max(0.0, d);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
out[t] = sum / max(1.0, f32(nMels));
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { MirGPU } from "./context";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
byteSizeF32,
|
|
5
|
+
createAndWriteStorageBuffer,
|
|
6
|
+
createReadbackBuffer,
|
|
7
|
+
createStorageOutBuffer,
|
|
8
|
+
createUniformBufferU32x4,
|
|
9
|
+
submitAndReadback,
|
|
10
|
+
type GpuDispatchResult,
|
|
11
|
+
} from "./helpers";
|
|
12
|
+
|
|
13
|
+
import { melProjectWGSL } from "./kernels/melProject.wgsl";
|
|
14
|
+
|
|
15
|
+
export type GpuMelProjectInput = {
|
|
16
|
+
nFrames: number;
|
|
17
|
+
nBins: number;
|
|
18
|
+
nMels: number;
|
|
19
|
+
magsFlat: Float32Array; // length = nFrames*nBins
|
|
20
|
+
filterFlat: Float32Array; // length = nMels*nBins
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type GpuMelProjectOutput = {
|
|
24
|
+
outFlat: Float32Array; // length = nFrames*nMels
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Real WebGPU compute stage: dense mel projection.
|
|
29
|
+
*
|
|
30
|
+
* Returns outFlat plus GPU timing that measures submit->readback.
|
|
31
|
+
*/
|
|
32
|
+
export async function gpuMelProjectFlat(
|
|
33
|
+
gpu: MirGPU,
|
|
34
|
+
input: GpuMelProjectInput
|
|
35
|
+
): Promise<GpuDispatchResult<GpuMelProjectOutput>> {
|
|
36
|
+
const { device } = gpu;
|
|
37
|
+
|
|
38
|
+
const { nFrames, nBins, nMels, magsFlat, filterFlat } = input;
|
|
39
|
+
if (magsFlat.length !== nFrames * nBins) {
|
|
40
|
+
throw new Error("@octoseq/mir: magsFlat length mismatch");
|
|
41
|
+
}
|
|
42
|
+
if (filterFlat.length !== nMels * nBins) {
|
|
43
|
+
throw new Error("@octoseq/mir: filterFlat length mismatch");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const magsBuffer = createAndWriteStorageBuffer(gpu, magsFlat);
|
|
47
|
+
const filterBuffer = createAndWriteStorageBuffer(gpu, filterFlat);
|
|
48
|
+
|
|
49
|
+
const outByteLen = byteSizeF32(nFrames * nMels);
|
|
50
|
+
const outBuffer = createStorageOutBuffer(gpu, outByteLen);
|
|
51
|
+
const readback = createReadbackBuffer(gpu, outByteLen);
|
|
52
|
+
|
|
53
|
+
const shader = device.createShaderModule({ code: melProjectWGSL });
|
|
54
|
+
const pipeline = device.createComputePipeline({
|
|
55
|
+
layout: "auto",
|
|
56
|
+
compute: {
|
|
57
|
+
module: shader,
|
|
58
|
+
entryPoint: "main",
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const params = createUniformBufferU32x4(gpu, new Uint32Array([nBins, nMels, nFrames, 0]));
|
|
63
|
+
|
|
64
|
+
const bindGroup = device.createBindGroup({
|
|
65
|
+
layout: pipeline.getBindGroupLayout(0),
|
|
66
|
+
entries: [
|
|
67
|
+
{ binding: 0, resource: { buffer: magsBuffer } },
|
|
68
|
+
{ binding: 1, resource: { buffer: filterBuffer } },
|
|
69
|
+
{ binding: 2, resource: { buffer: outBuffer } },
|
|
70
|
+
{ binding: 3, resource: { buffer: params } },
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const encoder = device.createCommandEncoder();
|
|
75
|
+
const pass = encoder.beginComputePass();
|
|
76
|
+
pass.setPipeline(pipeline);
|
|
77
|
+
pass.setBindGroup(0, bindGroup);
|
|
78
|
+
|
|
79
|
+
const wgX = Math.ceil(nFrames / 16);
|
|
80
|
+
const wgY = Math.ceil(nMels / 16);
|
|
81
|
+
pass.dispatchWorkgroups(wgX, wgY);
|
|
82
|
+
pass.end();
|
|
83
|
+
|
|
84
|
+
const { value: bytes, timing } = await submitAndReadback(gpu, encoder, outBuffer, readback, outByteLen);
|
|
85
|
+
|
|
86
|
+
// Cleanup (simple; no pooling in v0.1)
|
|
87
|
+
magsBuffer.destroy();
|
|
88
|
+
filterBuffer.destroy();
|
|
89
|
+
outBuffer.destroy();
|
|
90
|
+
params.destroy();
|
|
91
|
+
readback.destroy();
|
|
92
|
+
|
|
93
|
+
const outFlat = new Float32Array(bytes);
|
|
94
|
+
return {
|
|
95
|
+
value: { outFlat },
|
|
96
|
+
timing,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { MirGPU } from "./context";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
byteSizeF32,
|
|
5
|
+
createAndWriteStorageBuffer,
|
|
6
|
+
createReadbackBuffer,
|
|
7
|
+
createStorageOutBuffer,
|
|
8
|
+
createUniformBufferU32x4,
|
|
9
|
+
submitAndReadback,
|
|
10
|
+
type GpuDispatchResult,
|
|
11
|
+
} from "./helpers";
|
|
12
|
+
|
|
13
|
+
import { onsetEnvelopeWGSL } from "./kernels/onsetEnvelope.wgsl";
|
|
14
|
+
|
|
15
|
+
export type GpuOnsetEnvelopeInput = {
|
|
16
|
+
nFrames: number;
|
|
17
|
+
nMels: number;
|
|
18
|
+
melFlat: Float32Array; // length=nFrames*nMels
|
|
19
|
+
diffMethod: "rectified" | "abs";
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type GpuOnsetEnvelopeOutput = {
|
|
23
|
+
out: Float32Array; // length=nFrames
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export async function gpuOnsetEnvelopeFromMelFlat(
|
|
27
|
+
gpu: MirGPU,
|
|
28
|
+
input: GpuOnsetEnvelopeInput
|
|
29
|
+
): Promise<GpuDispatchResult<GpuOnsetEnvelopeOutput>> {
|
|
30
|
+
const { device } = gpu;
|
|
31
|
+
|
|
32
|
+
const { nFrames, nMels, melFlat, diffMethod } = input;
|
|
33
|
+
if (melFlat.length !== nFrames * nMels) {
|
|
34
|
+
throw new Error("@octoseq/mir: melFlat length mismatch");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const melBuffer = createAndWriteStorageBuffer(gpu, melFlat);
|
|
38
|
+
|
|
39
|
+
const outByteLen = byteSizeF32(nFrames);
|
|
40
|
+
const outBuffer = createStorageOutBuffer(gpu, outByteLen);
|
|
41
|
+
const readback = createReadbackBuffer(gpu, outByteLen);
|
|
42
|
+
|
|
43
|
+
const shader = device.createShaderModule({ code: onsetEnvelopeWGSL });
|
|
44
|
+
const pipeline = device.createComputePipeline({
|
|
45
|
+
layout: "auto",
|
|
46
|
+
compute: { module: shader, entryPoint: "main" },
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const diffU32 = diffMethod === "abs" ? 1 : 0;
|
|
50
|
+
const params = createUniformBufferU32x4(gpu, new Uint32Array([nMels, nFrames, diffU32, 0]));
|
|
51
|
+
|
|
52
|
+
const bindGroup = device.createBindGroup({
|
|
53
|
+
layout: pipeline.getBindGroupLayout(0),
|
|
54
|
+
entries: [
|
|
55
|
+
{ binding: 0, resource: { buffer: melBuffer } },
|
|
56
|
+
{ binding: 1, resource: { buffer: outBuffer } },
|
|
57
|
+
{ binding: 2, resource: { buffer: params } },
|
|
58
|
+
],
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const encoder = device.createCommandEncoder();
|
|
62
|
+
const pass = encoder.beginComputePass();
|
|
63
|
+
pass.setPipeline(pipeline);
|
|
64
|
+
pass.setBindGroup(0, bindGroup);
|
|
65
|
+
|
|
66
|
+
const wg = Math.ceil(nFrames / 256);
|
|
67
|
+
pass.dispatchWorkgroups(wg);
|
|
68
|
+
pass.end();
|
|
69
|
+
|
|
70
|
+
const { value: bytes, timing } = await submitAndReadback(gpu, encoder, outBuffer, readback, outByteLen);
|
|
71
|
+
|
|
72
|
+
melBuffer.destroy();
|
|
73
|
+
outBuffer.destroy();
|
|
74
|
+
params.destroy();
|
|
75
|
+
readback.destroy();
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
value: { out: new Float32Array(bytes) },
|
|
79
|
+
timing,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal WebGPU type declarations.
|
|
3
|
+
*
|
|
4
|
+
* Why this exists:
|
|
5
|
+
* - TypeScript's built-in lib set does not always include WebGPU types in all environments.
|
|
6
|
+
* - We avoid adding extra dependencies in this scaffold package.
|
|
7
|
+
*
|
|
8
|
+
* These declarations are intentionally minimal and are designed to *merge* with real WebGPU
|
|
9
|
+
* types when they are available (interface merging), rather than conflicting.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export { };
|
|
13
|
+
|
|
14
|
+
declare global {
|
|
15
|
+
interface Navigator {
|
|
16
|
+
gpu?: GPU;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface GPU {
|
|
20
|
+
requestAdapter(options?: GPURequestAdapterOptions): Promise<GPUAdapter | null>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface GPURequestAdapterOptions {
|
|
24
|
+
powerPreference?: "low-power" | "high-performance";
|
|
25
|
+
forceFallbackAdapter?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface GPUAdapter {
|
|
29
|
+
requestDevice(descriptor?: GPUDeviceDescriptor): Promise<GPUDevice>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface GPUDeviceDescriptor {
|
|
33
|
+
requiredFeatures?: Iterable<string>;
|
|
34
|
+
requiredLimits?: Record<string, number>;
|
|
35
|
+
label?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface GPUDevice {
|
|
39
|
+
readonly queue: GPUQueue;
|
|
40
|
+
createBuffer(descriptor: GPUBufferDescriptor): GPUBuffer;
|
|
41
|
+
createShaderModule(descriptor: GPUShaderModuleDescriptor): GPUShaderModule;
|
|
42
|
+
createComputePipeline(descriptor: GPUComputePipelineDescriptor): GPUComputePipeline;
|
|
43
|
+
createBindGroupLayout(descriptor: GPUBindGroupLayoutDescriptor): GPUBindGroupLayout;
|
|
44
|
+
createPipelineLayout(descriptor: GPUPipelineLayoutDescriptor): GPUPipelineLayout;
|
|
45
|
+
createBindGroup(descriptor: GPUBindGroupDescriptor): GPUBindGroup;
|
|
46
|
+
createCommandEncoder(descriptor?: GPUCommandEncoderDescriptor): GPUCommandEncoder;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface GPUQueue {
|
|
50
|
+
writeBuffer(
|
|
51
|
+
buffer: GPUBuffer,
|
|
52
|
+
bufferOffset: number,
|
|
53
|
+
data: BufferSource,
|
|
54
|
+
dataOffset?: number,
|
|
55
|
+
size?: number
|
|
56
|
+
): void;
|
|
57
|
+
submit(commandBuffers: Iterable<GPUCommandBuffer>): void;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface GPUBuffer {
|
|
61
|
+
mapAsync(mode: number, offset?: number, size?: number): Promise<void>;
|
|
62
|
+
getMappedRange(offset?: number, size?: number): ArrayBuffer;
|
|
63
|
+
unmap(): void;
|
|
64
|
+
destroy(): void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface GPUBufferDescriptor {
|
|
68
|
+
size: number;
|
|
69
|
+
usage: number;
|
|
70
|
+
mappedAtCreation?: boolean;
|
|
71
|
+
label?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
75
|
+
interface GPUShaderModule { }
|
|
76
|
+
|
|
77
|
+
interface GPUShaderModuleDescriptor {
|
|
78
|
+
code: string;
|
|
79
|
+
label?: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
interface GPUComputePipeline {
|
|
83
|
+
getBindGroupLayout(index: number): GPUBindGroupLayout;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
interface GPUComputePipelineDescriptor {
|
|
87
|
+
layout?: GPUPipelineLayout | "auto";
|
|
88
|
+
compute: {
|
|
89
|
+
module: GPUShaderModule;
|
|
90
|
+
entryPoint: string;
|
|
91
|
+
};
|
|
92
|
+
label?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
96
|
+
interface GPUBindGroupLayout { }
|
|
97
|
+
|
|
98
|
+
interface GPUBindGroupLayoutDescriptor {
|
|
99
|
+
entries: Array<{
|
|
100
|
+
binding: number;
|
|
101
|
+
visibility: number;
|
|
102
|
+
buffer?: { type?: "uniform" | "storage" | "read-only-storage" };
|
|
103
|
+
}>;
|
|
104
|
+
label?: string;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
108
|
+
interface GPUPipelineLayout { }
|
|
109
|
+
|
|
110
|
+
interface GPUPipelineLayoutDescriptor {
|
|
111
|
+
bindGroupLayouts: GPUBindGroupLayout[];
|
|
112
|
+
label?: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
116
|
+
interface GPUBindGroup { }
|
|
117
|
+
|
|
118
|
+
interface GPUBindGroupDescriptor {
|
|
119
|
+
layout: GPUBindGroupLayout;
|
|
120
|
+
entries: Array<{ binding: number; resource: { buffer: GPUBuffer } }>;
|
|
121
|
+
label?: string;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
interface GPUCommandEncoder {
|
|
125
|
+
beginComputePass(descriptor?: GPUComputePassDescriptor): GPUComputePassEncoder;
|
|
126
|
+
copyBufferToBuffer(
|
|
127
|
+
source: GPUBuffer,
|
|
128
|
+
sourceOffset: number,
|
|
129
|
+
destination: GPUBuffer,
|
|
130
|
+
destinationOffset: number,
|
|
131
|
+
size: number
|
|
132
|
+
): void;
|
|
133
|
+
finish(): GPUCommandBuffer;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
interface GPUCommandEncoderDescriptor {
|
|
137
|
+
label?: string;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
interface GPUComputePassEncoder {
|
|
141
|
+
setPipeline(pipeline: GPUComputePipeline): void;
|
|
142
|
+
setBindGroup(index: number, bindGroup: GPUBindGroup): void;
|
|
143
|
+
dispatchWorkgroups(
|
|
144
|
+
workgroupCountX: number,
|
|
145
|
+
workgroupCountY?: number,
|
|
146
|
+
workgroupCountZ?: number
|
|
147
|
+
): void;
|
|
148
|
+
end(): void;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
interface GPUComputePassDescriptor {
|
|
152
|
+
label?: string;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
156
|
+
interface GPUCommandBuffer { }
|
|
157
|
+
|
|
158
|
+
// Common WebGPU constants. These are numbers in the real API.
|
|
159
|
+
// We declare them as `var` so they exist at runtime only if provided by the environment.
|
|
160
|
+
// (We only use these constants when running in a WebGPU-capable browser.)
|
|
161
|
+
var GPUBufferUsage: {
|
|
162
|
+
MAP_READ: number;
|
|
163
|
+
COPY_DST: number;
|
|
164
|
+
COPY_SRC: number;
|
|
165
|
+
STORAGE: number;
|
|
166
|
+
UNIFORM: number;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
var GPUMapMode: {
|
|
170
|
+
READ: number;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
var GPUShaderStage: {
|
|
174
|
+
COMPUTE: number;
|
|
175
|
+
};
|
|
176
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
export type MirVersion = "0.1.0";
|
|
2
|
+
|
|
3
|
+
export type {
|
|
4
|
+
MirBackend,
|
|
5
|
+
MirRunTimings,
|
|
6
|
+
MirRunMeta,
|
|
7
|
+
Mir1DResult,
|
|
8
|
+
Mir2DResult,
|
|
9
|
+
MirResult,
|
|
10
|
+
MirFunctionId,
|
|
11
|
+
MirRunRequest,
|
|
12
|
+
MirAudioPayload
|
|
13
|
+
} from "./types";
|
|
14
|
+
|
|
15
|
+
export const MIR_VERSION: MirVersion = "0.1.0";
|
|
16
|
+
|
|
17
|
+
// ----------------------------
|
|
18
|
+
// Core Types
|
|
19
|
+
// ----------------------------
|
|
20
|
+
|
|
21
|
+
export type AudioBufferLike = {
|
|
22
|
+
sampleRate: number;
|
|
23
|
+
getChannelData(channel: number): Float32Array;
|
|
24
|
+
numberOfChannels: number;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// ----------------------------
|
|
28
|
+
// GPU
|
|
29
|
+
// ----------------------------
|
|
30
|
+
|
|
31
|
+
export { MirGPU } from "./gpu/context";
|
|
32
|
+
|
|
33
|
+
// ----------------------------
|
|
34
|
+
// Shared runner (main thread / worker)
|
|
35
|
+
// ----------------------------
|
|
36
|
+
|
|
37
|
+
export { runMir } from "./runner/runMir";
|
|
38
|
+
|
|
39
|
+
// ----------------------------
|
|
40
|
+
// Spectrogram (shared primitive)
|
|
41
|
+
// ----------------------------
|
|
42
|
+
|
|
43
|
+
export type { SpectrogramConfig, Spectrogram } from "./dsp/spectrogram";
|
|
44
|
+
export { spectrogram } from "./dsp/spectrogram";
|
|
45
|
+
|
|
46
|
+
// ----------------------------
|
|
47
|
+
// Derived spectral features (CPU, reuse spectrogram)
|
|
48
|
+
// ----------------------------
|
|
49
|
+
|
|
50
|
+
export { spectralCentroid, spectralFlux } from "./dsp/spectral";
|
|
51
|
+
|
|
52
|
+
// ----------------------------
|
|
53
|
+
// Onsets / Peaks
|
|
54
|
+
// ----------------------------
|
|
55
|
+
|
|
56
|
+
export type { OnsetEnvelope, OnsetEnvelopeOptions, OnsetEnvelopeGpuResult } from "./dsp/onset";
|
|
57
|
+
export { onsetEnvelopeFromSpectrogram, onsetEnvelopeFromMel, onsetEnvelopeFromMelGpu } from "./dsp/onset";
|
|
58
|
+
|
|
59
|
+
export type { PeakPickEvent, PeakPickOptions } from "./dsp/peakPick";
|
|
60
|
+
export { peakPick } from "./dsp/peakPick";
|
|
61
|
+
|
|
62
|
+
// ----------------------------
|
|
63
|
+
// HPSS
|
|
64
|
+
// ----------------------------
|
|
65
|
+
|
|
66
|
+
export type { SpectrogramLike2D, HpssOptions } from "./dsp/hpss";
|
|
67
|
+
export { hpss } from "./dsp/hpss";
|
|
68
|
+
|
|
69
|
+
// ----------------------------
|
|
70
|
+
// MFCC + Deltas
|
|
71
|
+
// ----------------------------
|
|
72
|
+
|
|
73
|
+
export type { MfccOptions, MfccResult, DeltaOptions, Features2D } from "./dsp/mfcc";
|
|
74
|
+
export { mfcc, delta, deltaDelta } from "./dsp/mfcc";
|
|
75
|
+
|
|
76
|
+
// ----------------------------
|
|
77
|
+
// Mel spectrogram
|
|
78
|
+
// ----------------------------
|
|
79
|
+
|
|
80
|
+
export type { MelConfig, MelSpectrogram } from "./dsp/mel";
|
|
81
|
+
export { melSpectrogram } from "./dsp/mel";
|
|
82
|
+
|
|
83
|
+
// ----------------------------
|
|
84
|
+
// Visualisation utilities
|
|
85
|
+
// ----------------------------
|
|
86
|
+
|
|
87
|
+
export { normaliseForWaveform } from "./util/normalise";
|
|
88
|
+
export type { Spectrogram2D, SpectrogramToDbOptions } from "./util/display";
|
|
89
|
+
export { spectrogramToDb, clampDb } from "./util/display";
|
|
90
|
+
|
|
91
|
+
// ----------------------------
|
|
92
|
+
// Utility helpers
|
|
93
|
+
// ----------------------------
|
|
94
|
+
|
|
95
|
+
export type { MinMax } from "./util/stats";
|
|
96
|
+
export { minMax } from "./util/stats";
|
|
97
|
+
|
|
98
|
+
// ----------------------------
|
|
99
|
+
// Search (deterministic within-track similarity)
|
|
100
|
+
// ----------------------------
|
|
101
|
+
|
|
102
|
+
export type { MirFingerprintV1 } from "./search/fingerprintV1";
|
|
103
|
+
export { fingerprintV1 } from "./search/fingerprintV1";
|
|
104
|
+
|
|
105
|
+
export type { MirFingerprintVectorWeights } from "./search/similarity";
|
|
106
|
+
export { fingerprintToVectorV1, similarityFingerprintV1 } from "./search/similarity";
|
|
107
|
+
|
|
108
|
+
export type { MirSearchCandidate, MirSearchOptionsV1, MirSearchResultV1 } from "./search/searchTrackV1";
|
|
109
|
+
export { searchTrackV1 } from "./search/searchTrackV1";
|
|
110
|
+
|
|
111
|
+
export type { MirRefinementCandidateLabelV1, MirSearchCurveKindV1, MirSearchGuidedOptionsV1, MirSearchResultV1Guided } from "./search/searchTrackV1Guided";
|
|
112
|
+
export { searchTrackV1Guided } from "./search/searchTrackV1Guided";
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Backwards-compat placeholder from the initial skeleton.
|
|
116
|
+
*
|
|
117
|
+
* Note: kept so existing internal references/tests don't break.
|
|
118
|
+
*/
|
|
119
|
+
export function helloMir(name = "world") {
|
|
120
|
+
return `Hello, ${name} from @octoseq/mir v${MIR_VERSION}`;
|
|
121
|
+
}
|