@ensomi/runtime 0.0.0 → 0.1.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.
Files changed (42) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +27 -0
  3. package/package.json +34 -3
  4. package/pkg/ensomi_generate_wasm.d.ts +109 -0
  5. package/pkg/ensomi_generate_wasm.js +806 -0
  6. package/pkg/ensomi_generate_wasm_bg.wasm +0 -0
  7. package/pkg/ensomi_generate_wasm_bg.wasm.d.ts +25 -0
  8. package/resampler/resample-11025-boundary.bin +0 -0
  9. package/resampler/resample-11025.bin +0 -0
  10. package/resampler/resample-11025.json +18 -0
  11. package/resampler/resample-16000-boundary.bin +0 -0
  12. package/resampler/resample-16000.bin +0 -0
  13. package/resampler/resample-16000.json +18 -0
  14. package/resampler/resample-192000-boundary.bin +0 -0
  15. package/resampler/resample-192000.bin +0 -0
  16. package/resampler/resample-192000.json +18 -0
  17. package/resampler/resample-24000-boundary.bin +0 -0
  18. package/resampler/resample-24000.bin +0 -0
  19. package/resampler/resample-24000.json +18 -0
  20. package/resampler/resample-32000-boundary.bin +0 -0
  21. package/resampler/resample-32000.bin +0 -0
  22. package/resampler/resample-32000.json +18 -0
  23. package/resampler/resample-44100-boundary.bin +0 -0
  24. package/resampler/resample-44100.bin +0 -0
  25. package/resampler/resample-44100.json +18 -0
  26. package/resampler/resample-48000-boundary.bin +0 -0
  27. package/resampler/resample-48000.bin +0 -0
  28. package/resampler/resample-48000.json +18 -0
  29. package/resampler/resample-88200-boundary.bin +0 -0
  30. package/resampler/resample-88200.bin +0 -0
  31. package/resampler/resample-88200.json +18 -0
  32. package/resampler/resample-96000-boundary.bin +0 -0
  33. package/resampler/resample-96000.bin +0 -0
  34. package/resampler/resample-96000.json +18 -0
  35. package/src/core.js +40 -0
  36. package/src/decode_audio.js +22 -0
  37. package/src/export.js +31 -0
  38. package/src/generate.js +73 -0
  39. package/src/index.d.ts +157 -0
  40. package/src/index.js +5 -0
  41. package/src/models.js +116 -0
  42. package/src/types.js +7 -0
Binary file
@@ -0,0 +1,25 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ export const memory: WebAssembly.Memory;
4
+ export const __wbg_replaydraws_free: (a: number, b: number) => void;
5
+ export const __wbg_wasmgenerator_free: (a: number, b: number) => void;
6
+ export const __wbg_wasmmodels_free: (a: number, b: number) => void;
7
+ export const replaydraws_add: (a: number, b: number, c: number, d: number, e: number, f: any, g: number) => void;
8
+ export const replaydraws_new: () => number;
9
+ export const replaydraws_recorded: (a: number) => number;
10
+ export const start: () => void;
11
+ export const wasmgenerator_new: (a: number, b: any, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: bigint, k: number, l: number, m: number, n: number, o: number, p: any, q: number) => [number, number, number];
12
+ export const wasmgenerator_step: (a: number, b: any) => [number, number, number];
13
+ export const wasmgenerator_work: (a: number) => number;
14
+ export const wasmmodels_capabilities: (a: number) => [number, number];
15
+ export const wasmmodels_new: (a: number, b: number, c: any) => [number, number, number];
16
+ export const wasmmodels_requiredFiles: (a: number, b: number) => [number, number, number];
17
+ export const wasmmodels_resamplerFiles: (a: number) => any;
18
+ export const __wbindgen_malloc: (a: number, b: number) => number;
19
+ export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
20
+ export const __wbindgen_exn_store: (a: number) => void;
21
+ export const __externref_table_alloc: () => number;
22
+ export const __wbindgen_externrefs: WebAssembly.Table;
23
+ export const __externref_table_dealloc: (a: number) => void;
24
+ export const __wbindgen_free: (a: number, b: number, c: number) => void;
25
+ export const __wbindgen_start: () => void;
Binary file
@@ -0,0 +1,18 @@
1
+ {
2
+ "sample_rate": 11025,
3
+ "target_rate": 22050,
4
+ "numerator": 1,
5
+ "phases": 2,
6
+ "radius": 128,
7
+ "dtype": "float64",
8
+ "shape": [
9
+ 2,
10
+ 257
11
+ ],
12
+ "file": "resample-11025.bin",
13
+ "boundary_frames": 128,
14
+ "boundary_samples": 192,
15
+ "boundary_file": "resample-11025-boundary.bin",
16
+ "algorithm": "soxr HQ polyphase FIR",
17
+ "soxr_version": "1.1.0"
18
+ }
Binary file
@@ -0,0 +1,18 @@
1
+ {
2
+ "sample_rate": 16000,
3
+ "target_rate": 22050,
4
+ "numerator": 320,
5
+ "phases": 441,
6
+ "radius": 128,
7
+ "dtype": "float64",
8
+ "shape": [
9
+ 441,
10
+ 257
11
+ ],
12
+ "file": "resample-16000.bin",
13
+ "boundary_frames": 128,
14
+ "boundary_samples": 221,
15
+ "boundary_file": "resample-16000-boundary.bin",
16
+ "algorithm": "soxr HQ polyphase FIR",
17
+ "soxr_version": "1.1.0"
18
+ }
Binary file
@@ -0,0 +1,18 @@
1
+ {
2
+ "sample_rate": 192000,
3
+ "target_rate": 22050,
4
+ "numerator": 1280,
5
+ "phases": 147,
6
+ "radius": 1115,
7
+ "dtype": "float64",
8
+ "shape": [
9
+ 147,
10
+ 2231
11
+ ],
12
+ "file": "resample-192000.bin",
13
+ "boundary_frames": 128,
14
+ "boundary_samples": 2230,
15
+ "boundary_file": "resample-192000-boundary.bin",
16
+ "algorithm": "soxr HQ polyphase FIR",
17
+ "soxr_version": "1.1.0"
18
+ }
Binary file
@@ -0,0 +1,18 @@
1
+ {
2
+ "sample_rate": 24000,
3
+ "target_rate": 22050,
4
+ "numerator": 160,
5
+ "phases": 147,
6
+ "radius": 140,
7
+ "dtype": "float64",
8
+ "shape": [
9
+ 147,
10
+ 281
11
+ ],
12
+ "file": "resample-24000.bin",
13
+ "boundary_frames": 128,
14
+ "boundary_samples": 280,
15
+ "boundary_file": "resample-24000-boundary.bin",
16
+ "algorithm": "soxr HQ polyphase FIR",
17
+ "soxr_version": "1.1.0"
18
+ }
Binary file
@@ -0,0 +1,18 @@
1
+ {
2
+ "sample_rate": 32000,
3
+ "target_rate": 22050,
4
+ "numerator": 640,
5
+ "phases": 441,
6
+ "radius": 186,
7
+ "dtype": "float64",
8
+ "shape": [
9
+ 441,
10
+ 373
11
+ ],
12
+ "file": "resample-32000.bin",
13
+ "boundary_frames": 128,
14
+ "boundary_samples": 372,
15
+ "boundary_file": "resample-32000-boundary.bin",
16
+ "algorithm": "soxr HQ polyphase FIR",
17
+ "soxr_version": "1.1.0"
18
+ }
Binary file
@@ -0,0 +1,18 @@
1
+ {
2
+ "sample_rate": 44100,
3
+ "target_rate": 22050,
4
+ "numerator": 2,
5
+ "phases": 1,
6
+ "radius": 256,
7
+ "dtype": "float64",
8
+ "shape": [
9
+ 1,
10
+ 513
11
+ ],
12
+ "file": "resample-44100.bin",
13
+ "boundary_frames": 128,
14
+ "boundary_samples": 512,
15
+ "boundary_file": "resample-44100-boundary.bin",
16
+ "algorithm": "soxr HQ polyphase FIR",
17
+ "soxr_version": "1.1.0"
18
+ }
Binary file
@@ -0,0 +1,18 @@
1
+ {
2
+ "sample_rate": 48000,
3
+ "target_rate": 22050,
4
+ "numerator": 320,
5
+ "phases": 147,
6
+ "radius": 279,
7
+ "dtype": "float64",
8
+ "shape": [
9
+ 147,
10
+ 559
11
+ ],
12
+ "file": "resample-48000.bin",
13
+ "boundary_frames": 128,
14
+ "boundary_samples": 558,
15
+ "boundary_file": "resample-48000-boundary.bin",
16
+ "algorithm": "soxr HQ polyphase FIR",
17
+ "soxr_version": "1.1.0"
18
+ }
Binary file
@@ -0,0 +1,18 @@
1
+ {
2
+ "sample_rate": 88200,
3
+ "target_rate": 22050,
4
+ "numerator": 4,
5
+ "phases": 1,
6
+ "radius": 512,
7
+ "dtype": "float64",
8
+ "shape": [
9
+ 1,
10
+ 1025
11
+ ],
12
+ "file": "resample-88200.bin",
13
+ "boundary_frames": 128,
14
+ "boundary_samples": 1024,
15
+ "boundary_file": "resample-88200-boundary.bin",
16
+ "algorithm": "soxr HQ polyphase FIR",
17
+ "soxr_version": "1.1.0"
18
+ }
Binary file
@@ -0,0 +1,18 @@
1
+ {
2
+ "sample_rate": 96000,
3
+ "target_rate": 22050,
4
+ "numerator": 640,
5
+ "phases": 147,
6
+ "radius": 558,
7
+ "dtype": "float64",
8
+ "shape": [
9
+ 147,
10
+ 1117
11
+ ],
12
+ "file": "resample-96000.bin",
13
+ "boundary_frames": 128,
14
+ "boundary_samples": 1116,
15
+ "boundary_file": "resample-96000-boundary.bin",
16
+ "algorithm": "soxr HQ polyphase FIR",
17
+ "soxr_version": "1.1.0"
18
+ }
package/src/core.js ADDED
@@ -0,0 +1,40 @@
1
+ import init, * as bindings from '../pkg/ensomi_generate_wasm.js';
2
+
3
+ let loaded, instance = 0;
4
+
5
+ /** Reads a `file:` URL in Node, whose `fetch` cannot read files. */
6
+ export async function readFile(url) {
7
+ const bytes = await process.getBuiltinModule('node:fs/promises').readFile(url);
8
+ return new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength);
9
+ }
10
+
11
+ /**
12
+ * Instantiates the Wasm core once. `wasm` is the module's bytes, a `WebAssembly.Module` or a URL; the
13
+ * default is the `.wasm` file beside the bindings, fetched in a browser and read from the file system in Node.
14
+ */
15
+ export function loadCore(wasm) {
16
+ const url = new URL('../pkg/ensomi_generate_wasm_bg.wasm', import.meta.url);
17
+ loaded ??= init({ module_or_path: wasm ?? (url.protocol === 'file:' ? readFile(url) : url) }).then(() => bindings);
18
+ return loaded;
19
+ }
20
+
21
+ /** Which instance of the core is current; a trap in `callCore` starts the next. */
22
+ export const coreInstance = () => instance;
23
+
24
+ /**
25
+ * Calls into the core. A trap (a panic, whose message the error carries, or memory or stack exhausted) can leave
26
+ * the instance's memory inconsistent, so the instance is replaced before the error is rethrown; objects of the
27
+ * old instance cannot be used after that.
28
+ */
29
+ export function callCore(call) {
30
+ try {
31
+ return call();
32
+ }
33
+ catch (error) {
34
+ if (error instanceof WebAssembly.RuntimeError) {
35
+ bindings.__wbg_reset_state();
36
+ instance++;
37
+ }
38
+ throw error;
39
+ }
40
+ }
@@ -0,0 +1,22 @@
1
+ /** Browser decode on two frontend clocks. WebAudio's codec/resampler can differ from Python's. */
2
+ export async function decodeAudio(arrayBuffer) {
3
+ if (!(arrayBuffer instanceof ArrayBuffer) || arrayBuffer.byteLength === 0)
4
+ throw new Error('Audio must be a nonempty ArrayBuffer');
5
+ const decode = async (rate) => {
6
+ const context = new OfflineAudioContext(1, 1, rate), buffer = await context.decodeAudioData(arrayBuffer.slice(0)), mono = new Float32Array(buffer.length);
7
+ for (let channel = 0; channel < buffer.numberOfChannels; channel++) {
8
+ const samples = buffer.getChannelData(channel);
9
+ for (let i = 0; i < mono.length; i++)
10
+ mono[i] += samples[i] / buffer.numberOfChannels;
11
+ }
12
+ return mono;
13
+ };
14
+ const [mel, beatthis] = await Promise.all([decode(24000), decode(22050)]);
15
+ let peak = 0;
16
+ for (const sample of mel)
17
+ peak = Math.max(peak, Math.abs(sample));
18
+ if (peak)
19
+ for (let i = 0; i < mel.length; i++)
20
+ mel[i] /= peak;
21
+ return { pcm: { samples: mel, channels: 1, mel, beatthis }, sampleRate: 24000 };
22
+ }
package/src/export.js ADDED
@@ -0,0 +1,31 @@
1
+ import { zipSync, strToU8 } from 'fflate';
2
+
3
+ /** Throws unless the chart's objects are sorted, in lanes 0 to 3, whole milliseconds and without overlap. */
4
+ export function validateChart(chart) {
5
+ if (!Number.isInteger(chart.duration_ms) || chart.duration_ms < 0)
6
+ throw new Error('Chart duration must be nonnegative whole milliseconds');
7
+ const end = [-1, -1, -1, -1];
8
+ let previous;
9
+ for (const object of chart.objects) {
10
+ const { lane, start_ms: start, end_ms: release } = object;
11
+ if (!Number.isInteger(lane) || lane < 0 || lane > 3 || !Number.isInteger(start) || start < 0 || start > chart.duration_ms)
12
+ throw new Error(`Invalid chart object: ${JSON.stringify(object)}`);
13
+ if (previous && (start < previous.start_ms || start === previous.start_ms && lane <= previous.lane))
14
+ throw new Error('Chart objects must be sorted by start then lane, with no duplicate heads');
15
+ if (start < end[lane])
16
+ throw new Error(`Head inside an open hold in lane ${lane} at ${start}`);
17
+ if (release !== undefined && (!Number.isInteger(release) || release <= start || release > chart.duration_ms))
18
+ throw new Error(`Invalid hold release in lane ${lane} at ${start}`);
19
+ end[lane] = release ?? start;
20
+ previous = object;
21
+ }
22
+ }
23
+
24
+ export function audioFilename(name) {
25
+ const ext = /\.([a-zA-Z0-9]+)$/.exec(name)?.[1].toLowerCase() ?? 'bin';
26
+ return `audio.${ext}`;
27
+ }
28
+
29
+ export function exportOsz(osu, audio, receiptJson) {
30
+ return zipSync({ 'generated.osu': strToU8(osu), [audioFilename(audio.name)]: [audio.bytes, { level: 0 }], 'receipt.json': strToU8(receiptJson + '\n') }, { level: 6 });
31
+ }
@@ -0,0 +1,73 @@
1
+ import { callCore, coreInstance } from './core.js';
2
+ import { exportOsz } from './export.js';
3
+
4
+ /** Lets queued tasks run, such as the WebGPU result that a graph run is waiting for. */
5
+ const pause = () => new Promise(resolve => {
6
+ const channel = new MessageChannel();
7
+ channel.port1.onmessage = () => {
8
+ channel.port1.close();
9
+ resolve();
10
+ };
11
+ channel.port2.postMessage(null);
12
+ });
13
+
14
+ /**
15
+ * Generates a chart. `pcm` is mono Float32Array/Float64Array or `{samples, channels, mel?, beatthis?}` with
16
+ * interleaved samples at `sampleRate`; `request` is a GenerateChartRequest.
17
+ * Options: `onProgress({phase})`, `audio` ({name, bytes}, adds an .osz), `setting` (difficulty name), `clock`
18
+ * (milliseconds, default `performance.now`), `replay` (a core `ReplayDraws`, moved into the generation, for
19
+ * conformance checks; the result then has `replayConsumed`, the number of draws used).
20
+ */
21
+ export async function generateChart(models, pcm, sampleRate, request, options = {}) {
22
+ if (options.random || options.trace)
23
+ throw new Error('The Wasm core takes recorded draws as options.replay and has no trace');
24
+ const audio = pcm instanceof Float32Array || pcm instanceof Float64Array ? { samples: pcm, channels: 1 } : pcm;
25
+ const seed = request.seed ?? 0;
26
+ if (typeof seed !== 'number' && typeof seed !== 'bigint' || typeof seed === 'number' && (!Number.isSafeInteger(seed) || seed < 0) || typeof seed === 'bigint' && (seed < 0n || seed > 0xffffffffffffffffn))
27
+ throw new Error('Seed must be an unsigned 64-bit integer; use bigint above the safe-number range');
28
+ await models.reloadCore();
29
+ const { core, wasm } = models;
30
+ const resamplerFiles = audio.beatthis ? null : core.WasmModels.resamplerFiles(sampleRate);
31
+ const resampler = resamplerFiles ? await Promise.all(Array.from(resamplerFiles, name => models.runtimeSource(name))) : undefined;
32
+ const { seed: _seed, ...rest } = request;
33
+ const clock = options.clock ?? (() => performance.now());
34
+ // decodeAudio passes its Mel stream as the samples too; the core then takes the stream once.
35
+ const samples = audio.mel && audio.beatthis && audio.samples === audio.mel ? new Float32Array(0) : audio.samples;
36
+ const generator = callCore(() => new core.WasmGenerator(wasm, samples, audio.channels, sampleRate, audio.mel, audio.beatthis, resampler, JSON.stringify(rest), BigInt(seed), typeof seed === 'bigint', options.setting, options.audio?.name, clock, options.replay));
37
+ const instance = coreInstance();
38
+ try {
39
+ let outputs;
40
+ for (;;) {
41
+ const step = callCore(() => generator.step(outputs));
42
+ outputs = undefined;
43
+ if (step.kind === 'progress') {
44
+ options.onProgress?.({ phase: step.phase });
45
+ }
46
+ else if (step.kind === 'run') {
47
+ const feeds = {};
48
+ for (const [name, tensor] of Object.entries(step.inputs))
49
+ feeds[name] = new models.ort.Tensor(tensor.type, tensor.data, tensor.dims);
50
+ // While the graph runs (BeatThis on the GPU), the core does what needs no outputs, yielding between
51
+ // slices so that the outputs are taken as soon as they arrive.
52
+ let running = true;
53
+ const run = models.sessions[step.graph].run(feeds);
54
+ run.then(() => { running = false; }, () => { running = false; });
55
+ while (running && callCore(() => generator.work()))
56
+ await pause();
57
+ const result = await run;
58
+ outputs = {};
59
+ for (const [name, tensor] of Object.entries(result))
60
+ outputs[name] = { type: tensor.type, dims: Array.from(tensor.dims), data: tensor.data };
61
+ }
62
+ else {
63
+ const { chart, osu, receipt, replay_consumed: replayConsumed } = step;
64
+ const osz = options.audio ? exportOsz(osu, options.audio, receipt.receipt_json) : undefined;
65
+ return { chart, receipt: { model_name: receipt.model_name, model_version: receipt.model_version, seed, star: receipt.star, receipt_json: receipt.receipt_json }, osu, ...(osz ? { osz } : {}), ...(options.replay ? { replayConsumed } : {}) };
66
+ }
67
+ }
68
+ }
69
+ finally {
70
+ if (coreInstance() === instance)
71
+ generator.free();
72
+ }
73
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,157 @@
1
+ import type * as ORT from 'onnxruntime-web';
2
+
3
+ /** EnsomiProtocol 0.2 chart.proto field names and enum values. */
4
+ export interface ChartObject {
5
+ lane: number;
6
+ start_ms: number;
7
+ end_ms?: number;
8
+ }
9
+ export interface Chart {
10
+ duration_ms: number;
11
+ objects: ChartObject[];
12
+ }
13
+ export interface AudioAssetRef {
14
+ local_path?: string;
15
+ uri?: string;
16
+ asset_id?: string;
17
+ audio_length_ms?: number;
18
+ sha256_hex?: string;
19
+ }
20
+ export declare enum LongNoteAmount {
21
+ UNSPECIFIED = 0,
22
+ TAP_ONLY = 1,
23
+ HALF = 2,
24
+ NATURAL = 3
25
+ }
26
+ export declare enum PatternKind {
27
+ UNSPECIFIED = 0,
28
+ STREAM = 1,
29
+ JUMPSTREAM = 2,
30
+ CHORDSTREAM = 3,
31
+ JACK = 4,
32
+ CHORDJACK = 5
33
+ }
34
+ export declare enum ControlStatus {
35
+ UNSPECIFIED = 0,
36
+ WORKS = 1,
37
+ EXPERIMENTAL = 2,
38
+ NOT_WORKING = 3
39
+ }
40
+ export declare enum GenerationPhase {
41
+ UNSPECIFIED = 0,
42
+ LOADING = 1,
43
+ TIMING = 2,
44
+ ROWS = 3,
45
+ ARRANGEMENT = 4,
46
+ EXPORT = 5
47
+ }
48
+ export interface SectionRequest {
49
+ start_ms: number;
50
+ end_ms: number;
51
+ star?: number;
52
+ pattern?: {
53
+ kind: PatternKind;
54
+ strength: number;
55
+ };
56
+ }
57
+ export interface ChartControls {
58
+ long_notes?: LongNoteAmount;
59
+ sections?: SectionRequest[];
60
+ }
61
+ export interface GenerateChartRequest {
62
+ audio?: AudioAssetRef;
63
+ star: number;
64
+ seed?: number | bigint;
65
+ controls?: ChartControls;
66
+ title?: string;
67
+ artist?: string;
68
+ }
69
+ export interface ModelCapabilities {
70
+ model_name: string;
71
+ model_version: string;
72
+ files: {
73
+ path: string;
74
+ sha256_hex: string;
75
+ }[];
76
+ min_star: number;
77
+ max_star_exclusive: number;
78
+ controls: {
79
+ name: string;
80
+ status: ControlStatus;
81
+ note: string;
82
+ }[];
83
+ }
84
+ export interface GenerationProgress {
85
+ phase: GenerationPhase;
86
+ }
87
+ export interface GenerationReceipt {
88
+ model_name: string;
89
+ model_version: string;
90
+ seed: number | bigint;
91
+ star: number;
92
+ receipt_json: string;
93
+ osz_path?: string;
94
+ }
95
+ export interface GenerationResult {
96
+ chart: Chart;
97
+ receipt: GenerationReceipt;
98
+ osu: string;
99
+ osz?: Uint8Array;
100
+ }
101
+ export interface AudioPCM {
102
+ /** Interleaved samples at the sampleRate passed to generateChart. With both frontend streams it may be the
103
+ * `mel` array itself, as `decodeAudio` gives it; the core then takes that array once. */
104
+ samples: Float32Array | Float64Array;
105
+ channels: number;
106
+ /** Optional already-decoded frontend streams: mono, 24000 and 22050 Hz. */
107
+ mel?: Float32Array;
108
+ beatthis?: Float32Array;
109
+ }
110
+ export type PCM = Float32Array | Float64Array | AudioPCM;
111
+ export interface DecodedAudio {
112
+ pcm: AudioPCM;
113
+ sampleRate: number;
114
+ }
115
+ export interface EncodedAudio {
116
+ name: string;
117
+ bytes: Uint8Array;
118
+ }
119
+
120
+ export type Ort = typeof ORT;
121
+ export type FileSource = (relativePath: string) => Promise<Uint8Array>;
122
+ /** Reads files relative to a base URL, with `fetch` or, for a `file:` URL in Node, from the file system. */
123
+ export declare function urlSource(baseUrl: string): FileSource;
124
+ export declare function localFilesSource(files: Iterable<File>): FileSource;
125
+
126
+ export declare class Models {
127
+ readonly capabilities: ModelCapabilities;
128
+ readonly ort: Ort;
129
+ readonly sessions: Record<string, ORT.InferenceSession>;
130
+ dispose(): Promise<void>;
131
+ }
132
+ export interface LoadModelsOptions {
133
+ ort?: Ort;
134
+ session?: ORT.InferenceSession.SessionOptions;
135
+ backend?: 'webgpu' | 'wasm';
136
+ /** ORT WebAssembly settings applied before sessions are created, e.g. wasmPaths and numThreads. */
137
+ wasm?: Partial<ORT.Env.WebAssemblyFlags>;
138
+ /** Reads the `resample-*` tables, needed for raw PCM at a rate other than 22050 Hz without a `beatthis` stream.
139
+ * Default: the package's `resampler/` directory. */
140
+ runtimeSource?: FileSource;
141
+ /** The Wasm core: bytes, a `WebAssembly.Module` or a URL. Default: the package's `pkg/ensomi_generate_wasm_bg.wasm`. */
142
+ core?: BufferSource | WebAssembly.Module | URL | string;
143
+ }
144
+ export declare function loadModels(source: FileSource | string, options?: LoadModelsOptions): Promise<Models>;
145
+
146
+ export interface GenerateOptions {
147
+ onProgress?: (progress: GenerationProgress) => void;
148
+ audio?: EncodedAudio;
149
+ setting?: string;
150
+ /** Milliseconds from any fixed origin; the receipt's timings come from it. Default `performance.now`. */
151
+ clock?: () => number;
152
+ /** Recorded draws of a release recording, for conformance checks. */
153
+ replay?: unknown;
154
+ }
155
+ export declare function generateChart(models: Models, pcm: PCM, sampleRate: number, request: GenerateChartRequest, options?: GenerateOptions): Promise<GenerationResult>;
156
+ export declare function decodeAudio(arrayBuffer: ArrayBuffer): Promise<DecodedAudio>;
157
+ export declare function validateChart(chart: Chart): void;
package/src/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { loadModels, urlSource, localFilesSource, Models } from './models.js';
2
+ export { generateChart } from './generate.js';
3
+ export { decodeAudio } from './decode_audio.js';
4
+ export { validateChart } from './export.js';
5
+ export * from './types.js';