@algo-wasm/algo-wasm 1.0.0 → 1.2.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 (61) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/README.md +6 -4
  3. package/dist/algo-wasm-error.d.ts +13 -0
  4. package/dist/algo-wasm-player.d.ts +169 -0
  5. package/dist/algo_wasm.wasm +0 -0
  6. package/dist/built-in-profiles.d.ts +5 -0
  7. package/dist/engine-core.d.ts +96 -0
  8. package/dist/events.d.ts +5 -1
  9. package/dist/index.d.ts +3 -4
  10. package/dist/index.js +1 -6
  11. package/dist/integrations/phaser.d.ts +9 -2
  12. package/dist/integrations/phaser.js +1 -16
  13. package/dist/integrations/react.d.ts +8 -2
  14. package/dist/integrations/react.js +1 -28
  15. package/dist/integrations/svelte.d.ts +6 -2
  16. package/dist/integrations/svelte.js +1 -17
  17. package/dist/integrations/vue.d.ts +7 -2
  18. package/dist/integrations/vue.js +1 -16
  19. package/dist/load-wasm.d.ts +92 -0
  20. package/dist/profile-schema.json +317 -228
  21. package/dist/profile-spec.d.ts +178 -0
  22. package/dist/profile-wire.d.ts +50 -0
  23. package/dist/profile.d.ts +25 -1
  24. package/dist/types.d.ts +25 -1
  25. package/dist/wire-decode.d.ts +18 -0
  26. package/dist/worklet/algo-worklet.d.ts +1 -83
  27. package/dist/worklet/algo-worklet.js +1 -471
  28. package/package.json +1 -1
  29. package/dist/AlgoWasmError.d.ts +0 -8
  30. package/dist/AlgoWasmError.d.ts.map +0 -1
  31. package/dist/AlgoWasmError.js +0 -9
  32. package/dist/AlgoWasmError.js.map +0 -1
  33. package/dist/AlgoWasmPlayer.d.ts +0 -48
  34. package/dist/AlgoWasmPlayer.d.ts.map +0 -1
  35. package/dist/AlgoWasmPlayer.js +0 -375
  36. package/dist/AlgoWasmPlayer.js.map +0 -1
  37. package/dist/events.d.ts.map +0 -1
  38. package/dist/events.js +0 -25
  39. package/dist/events.js.map +0 -1
  40. package/dist/index.d.ts.map +0 -1
  41. package/dist/index.js.map +0 -1
  42. package/dist/integrations/phaser.d.ts.map +0 -1
  43. package/dist/integrations/phaser.js.map +0 -1
  44. package/dist/integrations/react.d.ts.map +0 -1
  45. package/dist/integrations/react.js.map +0 -1
  46. package/dist/integrations/svelte.d.ts.map +0 -1
  47. package/dist/integrations/svelte.js.map +0 -1
  48. package/dist/integrations/vue.d.ts.map +0 -1
  49. package/dist/integrations/vue.js.map +0 -1
  50. package/dist/loadWasm.d.ts +0 -47
  51. package/dist/loadWasm.d.ts.map +0 -1
  52. package/dist/loadWasm.js +0 -229
  53. package/dist/loadWasm.js.map +0 -1
  54. package/dist/profile.d.ts.map +0 -1
  55. package/dist/profile.js +0 -525
  56. package/dist/profile.js.map +0 -1
  57. package/dist/types.d.ts.map +0 -1
  58. package/dist/types.js +0 -2
  59. package/dist/types.js.map +0 -1
  60. package/dist/worklet/algo-worklet.d.ts.map +0 -1
  61. package/dist/worklet/algo-worklet.js.map +0 -1
@@ -0,0 +1,178 @@
1
+ /** The allowed range of one numeric profile field. */
2
+ export interface FieldSpec {
3
+ min: number;
4
+ max: number;
5
+ /** True when the value must be a whole number. */
6
+ integer?: boolean;
7
+ /** True when the field may be left out. */
8
+ optional?: boolean;
9
+ }
10
+ /**
11
+ * Every numeric field in a profile section, with its allowed range.
12
+ *
13
+ * This table is the single description of the profile's numeric limits. The
14
+ * runtime validator reads it, and the published JSON schema is generated from
15
+ * it, so the two cannot disagree. The engine repeats the same limits as a
16
+ * second line of defence.
17
+ */
18
+ export declare const SECTION_FIELDS: {
19
+ readonly tempo: {
20
+ readonly minBpm: FieldSpec;
21
+ readonly maxBpm: FieldSpec;
22
+ readonly defaultBpm: FieldSpec;
23
+ };
24
+ readonly chordRules: {
25
+ readonly cadenceWeight: {
26
+ readonly min: 0;
27
+ readonly max: 4;
28
+ };
29
+ readonly movementWeight: {
30
+ readonly min: 0;
31
+ readonly max: 4;
32
+ };
33
+ readonly suspendedChance: FieldSpec;
34
+ readonly brightBorrowChance: FieldSpec;
35
+ };
36
+ readonly rhythmRules: {
37
+ readonly kickDensity: FieldSpec;
38
+ readonly hatDensity: FieldSpec;
39
+ readonly percussionDensity: FieldSpec;
40
+ readonly fillChance: FieldSpec;
41
+ readonly halfTimeChance: FieldSpec;
42
+ };
43
+ readonly bassRules: {
44
+ readonly density: FieldSpec;
45
+ readonly slideChance: FieldSpec;
46
+ readonly accentChance: FieldSpec;
47
+ readonly octaveJumpChance: FieldSpec;
48
+ readonly sustainChance: FieldSpec;
49
+ };
50
+ readonly melodyRules: {
51
+ readonly density: FieldSpec;
52
+ readonly mutationChance: FieldSpec;
53
+ readonly callResponseChance: FieldSpec;
54
+ readonly maxRangeSemitones: {
55
+ readonly min: 1;
56
+ readonly max: 48;
57
+ readonly integer: true;
58
+ };
59
+ };
60
+ readonly arrangementRules: {
61
+ readonly minSectionBars: FieldSpec;
62
+ readonly maxSectionBars: FieldSpec;
63
+ readonly futureBars: FieldSpec;
64
+ readonly resetChance: FieldSpec;
65
+ };
66
+ readonly automationRules: {
67
+ readonly filterMotion: FieldSpec;
68
+ readonly sendMotion: FieldSpec;
69
+ readonly panMotion: FieldSpec;
70
+ };
71
+ readonly limits: {
72
+ readonly minSampleRate: {
73
+ readonly min: 22050;
74
+ readonly max: 96000;
75
+ readonly integer: true;
76
+ };
77
+ readonly maxSampleRate: {
78
+ readonly min: 22050;
79
+ readonly max: 96000;
80
+ readonly integer: true;
81
+ };
82
+ readonly minBpm: {
83
+ readonly min: 1;
84
+ readonly max: 1000;
85
+ };
86
+ readonly maxBpm: {
87
+ readonly min: 1;
88
+ readonly max: 1000;
89
+ };
90
+ readonly maxTracks: {
91
+ readonly min: 11;
92
+ readonly max: 11;
93
+ readonly integer: true;
94
+ };
95
+ readonly maxVoices: {
96
+ readonly min: 1;
97
+ readonly max: 64;
98
+ readonly integer: true;
99
+ };
100
+ readonly maxBarsQueued: {
101
+ readonly min: 1;
102
+ readonly max: 64;
103
+ readonly integer: true;
104
+ };
105
+ readonly maxEventsPerBlock: {
106
+ readonly min: 1;
107
+ readonly max: 512;
108
+ readonly integer: true;
109
+ };
110
+ };
111
+ };
112
+ /** Numeric fields of the mixer, apart from its per-track entries. */
113
+ export declare const MIXER_FIELDS: {
114
+ readonly masterGain: FieldSpec;
115
+ readonly limiterDrive: FieldSpec;
116
+ readonly delayFeedback: FieldSpec;
117
+ readonly reverbMix: FieldSpec;
118
+ };
119
+ /** Numeric fields of one patch. */
120
+ export declare const PATCH_FIELDS: {
121
+ readonly gain: FieldSpec;
122
+ readonly pan: FieldSpec;
123
+ readonly attackMs: FieldSpec;
124
+ readonly decayMs: FieldSpec;
125
+ readonly sustain: FieldSpec;
126
+ readonly releaseMs: FieldSpec;
127
+ readonly filterCutoff: {
128
+ readonly min: 20;
129
+ readonly max: 20000;
130
+ };
131
+ readonly resonance: FieldSpec;
132
+ readonly delaySend: FieldSpec;
133
+ readonly reverbSend: FieldSpec;
134
+ readonly detuneCents: {
135
+ readonly min: 0;
136
+ readonly max: 50;
137
+ readonly optional: true;
138
+ };
139
+ readonly filterEnvOctaves: {
140
+ readonly min: 0;
141
+ readonly max: 6;
142
+ readonly optional: true;
143
+ };
144
+ readonly filterEnvDecayMs: {
145
+ readonly min: 1;
146
+ readonly max: 10000;
147
+ readonly optional: true;
148
+ };
149
+ readonly lfoRate: {
150
+ readonly min: 0;
151
+ readonly max: 8;
152
+ readonly optional: true;
153
+ };
154
+ readonly lfoDepth: {
155
+ readonly min: 0;
156
+ readonly max: 4;
157
+ readonly optional: true;
158
+ };
159
+ readonly width: FieldSpec;
160
+ readonly duck: FieldSpec;
161
+ };
162
+ /** Numeric fields of one mixer track entry. */
163
+ export declare const MIXER_TRACK_FIELDS: {
164
+ readonly gain: FieldSpec;
165
+ readonly pan: FieldSpec;
166
+ };
167
+ /** Largest allowed scale weight. */
168
+ export declare const MAX_SCALE_WEIGHT = 1000000;
169
+ type JsonSchema = Record<string, unknown>;
170
+ /**
171
+ * Builds the JSON schema for a profile from the field tables.
172
+ *
173
+ * The build writes the result to `dist/profile-schema.json`. A schema cannot
174
+ * express every rule, such as the tempo range being ordered, so
175
+ * `validateProfile` remains the authority.
176
+ */
177
+ export declare function buildProfileSchema(): JsonSchema;
178
+ export {};
@@ -0,0 +1,50 @@
1
+ import type { AlgoWasmProfile } from './types.js';
2
+ /**
3
+ * Version of the flat profile layout. The engine checks it, so a package and
4
+ * a WASM binary from different releases fail loudly instead of misreading
5
+ * values.
6
+ */
7
+ export declare const PROFILE_WIRE_VERSION = 1;
8
+ /** Largest number of weighted scales a profile may list. */
9
+ export declare const MAX_SCALES = 8;
10
+ /** Track ids in the order the engine stores patches and mixer entries. */
11
+ export declare const WIRE_TRACK_IDS: readonly ['kick', 'snare', 'closed_hat', 'open_hat', 'percussion', 'bass', 'chords', 'pad', 'lead', 'arp', 'fx'];
12
+ /** Wave shapes in the order of their numeric ids. */
13
+ export declare const WIRE_WAVE_SHAPES: readonly ['sine', 'triangle', 'saw', 'square', 'pulse', 'noise'];
14
+ /** Scale names in the order of their numeric ids. */
15
+ export declare const WIRE_SCALE_NAMES: readonly ['natural_minor', 'dorian', 'aeolian', 'phrygian_dominant', 'minor_pentatonic'];
16
+ /** Mood ids in the order of their numeric ids. */
17
+ export declare const WIRE_MOODS: readonly ['dark', 'bright', 'tense', 'calm'];
18
+ /** Section names in the order of their numeric ids. */
19
+ export declare const WIRE_SECTIONS: readonly ['intro', 'groove_a', 'groove_b', 'build', 'drop', 'variation', 'breakdown', 'fill', 'transition', 'reset'];
20
+ /**
21
+ * Values used for the optional profile fields added in 1.2.0. Each default
22
+ * reproduces the behaviour of earlier releases, so older profiles keep
23
+ * composing the same songs.
24
+ */
25
+ export declare const PROFILE_DEFAULTS: {
26
+ readonly halfTimeChance: 0.3;
27
+ readonly sustainChance: 0;
28
+ readonly detuneCents: 0;
29
+ readonly filterEnvOctaves: 0;
30
+ readonly filterEnvDecayMs: 120;
31
+ readonly lfoRate: 0;
32
+ readonly lfoDepth: 0;
33
+ readonly width: 0;
34
+ readonly duck: 0;
35
+ };
36
+ /** Total number of values in the flat profile layout. */
37
+ export declare const PROFILE_WIRE_LENGTH: number;
38
+ /**
39
+ * Encodes a validated profile as the flat `Float32Array` the engine reads.
40
+ *
41
+ * The layout is `[version, tempo x3, chords x4, rhythm x5, bass x5, melody x4,
42
+ * arrangement x4, automation x3, mixer x4, limits x8, scale count,
43
+ * (scale id, weight) x8, patches x11, mixer tracks x11]`. Patches and mixer
44
+ * tracks are written in built-in track order whatever order the profile lists
45
+ * them in. The engine's `Profile::from_wire` reads the same layout.
46
+ *
47
+ * Call `validateProfile` first: this function assumes every field is present
48
+ * and of the right type.
49
+ */
50
+ export declare function encodeProfile(profile: AlgoWasmProfile): Float32Array;
package/dist/profile.d.ts CHANGED
@@ -1,15 +1,39 @@
1
1
  import type { AlgoWasmProfile } from './types.js';
2
+ /** The built-in track ids, in the engine's fixed order. */
2
3
  export declare const trackIds: readonly ["kick", "snare", "closed_hat", "open_hat", "percussion", "bass", "chords", "pad", "lead", "arp", "fx"];
4
+ /**
5
+ * Factories for the built-in profiles. Each call returns a fresh copy, so a
6
+ * profile can be edited without affecting later calls.
7
+ */
3
8
  export declare const builtInProfiles: {
9
+ /** Mid-1990s Amiga-inspired house with a four-on-the-floor kick. */
4
10
  amigaHouse95ish(): AlgoWasmProfile;
11
+ /** Slower broken-beat profile. */
5
12
  downtempoBreakbeat(): AlgoWasmProfile;
13
+ /** Deep, dub-flavoured house. */
6
14
  dubDeepHouse(): AlgoWasmProfile;
15
+ /** Half-time, sub-led dubstep with a wobbling mid bass. */
16
+ dubstep(): AlgoWasmProfile;
7
17
  };
18
+ /** Returns a deep copy of a profile. */
8
19
  export declare function cloneProfile(profile: AlgoWasmProfile): AlgoWasmProfile;
20
+ /**
21
+ * Checks an untrusted value against every profile rule and returns a deep
22
+ * copy typed as a profile.
23
+ *
24
+ * @throws {AlgoWasmError} With code `profile_invalid` and a message naming
25
+ * the field and its allowed range.
26
+ */
9
27
  export declare function validateProfile(profile: unknown): AlgoWasmProfile;
28
+ /**
29
+ * Converts a seed to an unsigned 64-bit integer. Larger values wrap.
30
+ *
31
+ * @throws {AlgoWasmError} With code `profile_invalid` when the seed is a
32
+ * negative or fractional number, or a string that is not decimal digits.
33
+ */
10
34
  export declare function normaliseSeed(seed: bigint | number | string | undefined): bigint;
35
+ /** Splits a 64-bit seed into the two 32-bit halves the engine takes. */
11
36
  export declare function splitSeed(seed: bigint): {
12
37
  high: number;
13
38
  low: number;
14
39
  };
15
- //# sourceMappingURL=profile.d.ts.map
package/dist/types.d.ts CHANGED
@@ -23,12 +23,23 @@ export interface AlgoWasmRhythmRules {
23
23
  hatDensity: number;
24
24
  percussionDensity: number;
25
25
  fillChance: number;
26
+ /**
27
+ * Chance, from 0 to 1, that a broken-beat song puts its snare on beat
28
+ * three only, for a half-time feel. Ignored when `kickDensity` is 1.
29
+ * Defaults to 0.3.
30
+ */
31
+ halfTimeChance?: number;
26
32
  }
27
33
  export interface AlgoWasmBassRules {
28
34
  density: number;
29
35
  slideChance: number;
30
36
  accentChance: number;
31
37
  octaveJumpChance: number;
38
+ /**
39
+ * Chance, from 0 to 1, that a song holds each bass note until the next one
40
+ * starts instead of using a short gate. Defaults to 0.
41
+ */
42
+ sustainChance?: number;
32
43
  }
33
44
  export interface AlgoWasmMelodyRules {
34
45
  density: number;
@@ -60,6 +71,20 @@ export interface AlgoWasmPatch {
60
71
  resonance: number;
61
72
  delaySend: number;
62
73
  reverbSend: number;
74
+ /** Detune of a second oscillator, in cents from 0 to 50. Defaults to 0 (off). */
75
+ detuneCents?: number;
76
+ /** How far the filter opens at note start, in octaves from 0 to 6. Defaults to 0. */
77
+ filterEnvOctaves?: number;
78
+ /** Time the filter envelope takes to close, from 1 to 10000 ms. Defaults to 120. */
79
+ filterEnvDecayMs?: number;
80
+ /** Tempo-synced filter LFO rate, in cycles per beat from 0 to 8. Defaults to 0 (off). */
81
+ lfoRate?: number;
82
+ /** Filter LFO depth, in octaves from 0 to 4. Defaults to 0. */
83
+ lfoDepth?: number;
84
+ /** Stereo spread of the track's notes, from 0 (centred) to 1. Defaults to 0. */
85
+ width?: number;
86
+ /** How much each kick ducks this track, from 0 (none) to 1. Defaults to 0. */
87
+ duck?: number;
63
88
  }
64
89
  export interface AlgoWasmMixerTrackProfile {
65
90
  track: AlgoWasmTrackId;
@@ -186,4 +211,3 @@ export interface AlgoWasmOfflineRenderOptions {
186
211
  export interface AlgoWasmMidiExportOptions {
187
212
  downloadName?: string;
188
213
  }
189
- //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,18 @@
1
+ import type { AlgoWasmGeneratedEvent, AlgoWasmSnapshot } from './types.js';
2
+ /** Number of values each event occupies in the engine's event buffer. */
3
+ export declare const EVENT_WIRE_SIZE = 5;
4
+ /** Number of values in the engine's binary snapshot. */
5
+ export declare const SNAPSHOT_WIRE_LENGTH: number;
6
+ /**
7
+ * Decodes the engine's binary snapshot.
8
+ *
9
+ * The layout is `[seed high, seed low, sample rate, bpm, bar, beat, section,
10
+ * energy, intensity, playing]`, then `[muted, solo, level]` for each track.
11
+ */
12
+ export declare function decodeSnapshot(wire: Float64Array): AlgoWasmSnapshot;
13
+ /**
14
+ * Decodes the engine's binary event buffer, five values per event:
15
+ * `[kind, sample, a, b, c]`. Kind 0 is note-on, 3 section-change, 4 bar, and
16
+ * 5 beat. Unknown kinds are skipped.
17
+ */
18
+ export declare function decodeEvents(wire: Float64Array): AlgoWasmGeneratedEvent[];
@@ -1,83 +1 @@
1
- declare const sampleRate: number;
2
- declare class AudioWorkletProcessor {
3
- readonly port: MessagePort;
4
- process(inputs: Float32Array[][], outputs: Float32Array[][], parameters: Record<string, Float32Array>): boolean;
5
- }
6
- declare function registerProcessor(name: string, processorCtor: typeof AudioWorkletProcessor): void;
7
- type WasmFn = (...args: number[]) => number;
8
- type WorkletCommand = {
9
- type: string;
10
- id?: number;
11
- wasmUrl?: string;
12
- wasmBytes?: ArrayBuffer;
13
- profile?: unknown;
14
- seed?: string;
15
- sampleRate?: number;
16
- volume?: number;
17
- value?: number;
18
- trackId?: string;
19
- muted?: boolean;
20
- solo?: boolean;
21
- mood?: string;
22
- minBpm?: number;
23
- maxBpm?: number;
24
- };
25
- type WorkletExports = Record<string, WebAssembly.ExportValue>;
26
- declare class WorkletWasmBinding {
27
- private readonly exports;
28
- private enginePtr;
29
- private renderPtr;
30
- private renderLength;
31
- private renderView?;
32
- constructor(instance: WebAssembly.Instance);
33
- create(profile: unknown, seed: string, requestedSampleRate: number, volume: number): void;
34
- start(): void;
35
- pause(): void;
36
- resume(): void;
37
- stop(): void;
38
- setSeed(seed: string): void;
39
- setProfile(profile: unknown): void;
40
- setVolume(value: number): void;
41
- setEnergy(value: number): void;
42
- setIntensity(value: number): void;
43
- setMood(mood: string): void;
44
- setTempoRange(minBpm: number, maxBpm: number): void;
45
- setMuted(trackId: string, muted: boolean): void;
46
- setSolo(trackId: string, solo: boolean): void;
47
- renderTo(output: Float32Array): void;
48
- snapshot(): unknown;
49
- events(): unknown[];
50
- exportMidi(): Uint8Array;
51
- destroy(): void;
52
- private get memory();
53
- private ensureRenderBuffer;
54
- private writeString;
55
- private readJson;
56
- private callCode;
57
- private assertCode;
58
- private call;
59
- private lastError;
60
- }
61
- declare class AlgoWasmProcessor extends AudioWorkletProcessor {
62
- private binding?;
63
- private playing;
64
- private scratch;
65
- private eventCountdown;
66
- private commandQueue;
67
- constructor();
68
- process(_inputs: Float32Array[][], outputs: Float32Array[][], _parameters: Record<string, Float32Array>): boolean;
69
- private handleCommand;
70
- private configure;
71
- private applyCommand;
72
- private requireBinding;
73
- private reply;
74
- }
75
- declare function instantiateWorkletWasm(url: string | undefined, wasmBytes: ArrayBuffer | undefined): Promise<WebAssembly.Instance>;
76
- declare function splitSeed(seed: string): {
77
- high: number;
78
- low: number;
79
- };
80
- declare function clampUnit(value: number): number;
81
- declare function encodeUtf8(value: string): Uint8Array;
82
- declare function decodeUtf8(bytes: Uint8Array): string;
83
- //# sourceMappingURL=algo-worklet.d.ts.map
1
+ export {};