zx-kit 0.26.0 → 0.27.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/README.md +54 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/music.d.ts +61 -0
- package/dist/music.d.ts.map +1 -0
- package/dist/music.js +89 -0
- package/dist/music.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -572,6 +572,7 @@ requestAnimationFrame(loop)
|
|
|
572
572
|
| [`font.ts`](#fontts--rom-bitmap-font) | 96-character ROM font, raw bitmap access |
|
|
573
573
|
| [`i18n.ts`](#i18nts--runtime-locale-selection) | Type-safe runtime locale selection for translated string packs |
|
|
574
574
|
| [`lighting.ts`](#lightingts--dithered-cave-darkness) | Dithered cave darkness: pre-baked level tiles + dirty-cell buffer, one blit/frame (no per-frame putImageData) |
|
|
575
|
+
| [`music.ts`](#musicts--note-name-ay-music) | Write AY music by note name (`A5`, `C#4`) and loop it for background tracks |
|
|
575
576
|
|
|
576
577
|
---
|
|
577
578
|
|
|
@@ -2669,6 +2670,59 @@ The `darknessAt` callback is where you add **depth gradients** (darker the deepe
|
|
|
2669
2670
|
|
|
2670
2671
|
---
|
|
2671
2672
|
|
|
2673
|
+
## `music.ts` — Note-Name AY Music
|
|
2674
|
+
|
|
2675
|
+
Write AY tunes by **note name** instead of raw frequencies, and **loop** them for
|
|
2676
|
+
background music. A thin, friendly layer over [`playAY`](#playaypattern-startdelay-void):
|
|
2677
|
+
the AY chip already plays three channels of `AYNote`s — this lets you *author* and
|
|
2678
|
+
*repeat* them without the maths (so "I don't read note tables" is no longer a blocker).
|
|
2679
|
+
|
|
2680
|
+
### `noteToFreq(name): number`
|
|
2681
|
+
|
|
2682
|
+
Note name → frequency (Hz), equal temperament, **A4 = 440**. Accepts `A5`, `C#4`,
|
|
2683
|
+
`Db3`, `Fs5` (`s` = sharp). `r` / `-` is a rest → `0` (a silent note). Throws on a
|
|
2684
|
+
malformed name. Pure.
|
|
2685
|
+
|
|
2686
|
+
```ts
|
|
2687
|
+
noteToFreq('A4') // 440
|
|
2688
|
+
noteToFreq('C4') // 261.63 (middle C)
|
|
2689
|
+
noteToFreq('A5') // 880
|
|
2690
|
+
```
|
|
2691
|
+
|
|
2692
|
+
### `seq(spec, options?): AYNote[]`
|
|
2693
|
+
|
|
2694
|
+
Parses a compact note string into one channel's `AYNote[]`. Tokens are
|
|
2695
|
+
whitespace-separated `Note` or `Note:durMs`; `r` (or `-`) is a rest. `options.dur`
|
|
2696
|
+
sets the default duration (200 ms); `options.noise` / `noisePeriod` mix LFSR noise
|
|
2697
|
+
into every note (handy for a texture/percussion channel).
|
|
2698
|
+
|
|
2699
|
+
```ts
|
|
2700
|
+
seq('A4 C5:400 r:200 E5') // A4 @default, C5 @400ms, rest @200ms, E5 @default
|
|
2701
|
+
seq('r r r r', { dur: 240, noise: true }) // a noise-only texture line
|
|
2702
|
+
```
|
|
2703
|
+
|
|
2704
|
+
### `playAYLoop(pattern): { stop() }`
|
|
2705
|
+
|
|
2706
|
+
Plays a 3-channel pattern **on repeat** — background music. Re-schedules each loop
|
|
2707
|
+
after the pattern's length (its longest channel) and returns a handle to `stop()`.
|
|
2708
|
+
No-ops (returns a do-nothing stop) when there's no audio context yet or the pattern
|
|
2709
|
+
is empty. Call after a user gesture has unlocked audio.
|
|
2710
|
+
|
|
2711
|
+
```ts
|
|
2712
|
+
const track = playAYLoop({
|
|
2713
|
+
a: seq('A4 C5 E5 C5', { dur: 240 }), // melody
|
|
2714
|
+
b: seq('A2:480 E2:480', { dur: 480 }), // slow bass drone
|
|
2715
|
+
c: seq('r r r r', { dur: 240, noise: true }), // texture
|
|
2716
|
+
})
|
|
2717
|
+
// later…
|
|
2718
|
+
track.stop()
|
|
2719
|
+
```
|
|
2720
|
+
|
|
2721
|
+
> Looping re-schedules at the pattern boundary via a timer — fine for ambient /
|
|
2722
|
+
> background loops; for tight musical sync you'd want a sample-accurate scheduler.
|
|
2723
|
+
|
|
2724
|
+
---
|
|
2725
|
+
|
|
2672
2726
|
## Architecture
|
|
2673
2727
|
|
|
2674
2728
|
### Module structure
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA"}
|
package/dist/music.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module music
|
|
3
|
+
*
|
|
4
|
+
* Write AY music by **note name** instead of raw frequencies, and **loop** it for
|
|
5
|
+
* background tracks. A thin, friendly layer over {@link playAY} (the AY chip
|
|
6
|
+
* already plays three channels of {@link AYNote}s — this just lets you author and
|
|
7
|
+
* repeat them without doing the maths).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { seq, playAYLoop, noteToFreq } from 'zx-kit'
|
|
12
|
+
*
|
|
13
|
+
* const loop = playAYLoop({
|
|
14
|
+
* a: seq('A4 C5 E5 C5', { dur: 240 }), // melody by name
|
|
15
|
+
* b: seq('A2:480 E2:480', { dur: 480 }), // slow bass drone
|
|
16
|
+
* c: seq('r r r r', { dur: 240, noise: true }), // a little texture
|
|
17
|
+
* })
|
|
18
|
+
* // later: loop.stop()
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
import { type AYNote } from './ay.js';
|
|
22
|
+
/**
|
|
23
|
+
* Note name → frequency (Hz), equal temperament, A4 = 440. Accepts `A5`, `C#4`,
|
|
24
|
+
* `Db3`, `Fs5` (`s` = sharp); `r` / `-` is a rest → `0` (a silent {@link AYNote}).
|
|
25
|
+
* Throws on a malformed name.
|
|
26
|
+
*/
|
|
27
|
+
export declare function noteToFreq(name: string): number;
|
|
28
|
+
/** Options for {@link seq}. */
|
|
29
|
+
export interface SeqOptions {
|
|
30
|
+
/** Default note duration in ms when a token doesn't specify one (default 200). */
|
|
31
|
+
dur?: number;
|
|
32
|
+
/** Mix LFSR noise into every note (e.g. for a percussive/texture channel). */
|
|
33
|
+
noise?: boolean;
|
|
34
|
+
/** Noise period when `noise` is set. */
|
|
35
|
+
noisePeriod?: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Parses a compact note string into an {@link AYNote} array for one channel.
|
|
39
|
+
* Tokens are whitespace-separated `Note` or `Note:durMs`; `r` (or `-`) is a rest.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* seq('A4 C5:400 r:200 E5') // A4 @default, C5 @400ms, rest @200ms, E5 @default
|
|
43
|
+
*/
|
|
44
|
+
export declare function seq(spec: string, opts?: SeqOptions): AYNote[];
|
|
45
|
+
/** A running looped track. Call {@link LoopHandle.stop} to end it. */
|
|
46
|
+
export interface LoopHandle {
|
|
47
|
+
stop(): void;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Plays a 3-channel AY pattern on repeat — background music. Re-schedules each
|
|
51
|
+
* loop after the pattern's length (the longest channel). No-ops (returns a stop
|
|
52
|
+
* that does nothing) when there is no audio context yet or the pattern is empty.
|
|
53
|
+
*
|
|
54
|
+
* Call after the audio context is unlocked by a user gesture.
|
|
55
|
+
*/
|
|
56
|
+
export declare function playAYLoop(pattern: {
|
|
57
|
+
a?: AYNote[];
|
|
58
|
+
b?: AYNote[];
|
|
59
|
+
c?: AYNote[];
|
|
60
|
+
}): LoopHandle;
|
|
61
|
+
//# sourceMappingURL=music.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"music.d.ts","sourceRoot":"","sources":["../src/music.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,SAAS,CAAA;AAK7C;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAW/C;AAED,+BAA+B;AAC/B,MAAM,WAAW,UAAU;IACzB,kFAAkF;IAClF,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,8EAA8E;IAC9E,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;;;;;GAMG;AACH,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,EAAE,CAajE;AAED,sEAAsE;AACtE,MAAM,WAAW,UAAU;IACzB,IAAI,IAAI,IAAI,CAAA;CACb;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE;IAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,UAAU,CAa5F"}
|
package/dist/music.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module music
|
|
3
|
+
*
|
|
4
|
+
* Write AY music by **note name** instead of raw frequencies, and **loop** it for
|
|
5
|
+
* background tracks. A thin, friendly layer over {@link playAY} (the AY chip
|
|
6
|
+
* already plays three channels of {@link AYNote}s — this just lets you author and
|
|
7
|
+
* repeat them without doing the maths).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { seq, playAYLoop, noteToFreq } from 'zx-kit'
|
|
12
|
+
*
|
|
13
|
+
* const loop = playAYLoop({
|
|
14
|
+
* a: seq('A4 C5 E5 C5', { dur: 240 }), // melody by name
|
|
15
|
+
* b: seq('A2:480 E2:480', { dur: 480 }), // slow bass drone
|
|
16
|
+
* c: seq('r r r r', { dur: 240, noise: true }), // a little texture
|
|
17
|
+
* })
|
|
18
|
+
* // later: loop.stop()
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
import { playAY } from './ay.js';
|
|
22
|
+
import { getAudioContext } from './audio.js';
|
|
23
|
+
const SEMITONE = { c: 0, d: 2, e: 4, f: 5, g: 7, a: 9, b: 11 };
|
|
24
|
+
/**
|
|
25
|
+
* Note name → frequency (Hz), equal temperament, A4 = 440. Accepts `A5`, `C#4`,
|
|
26
|
+
* `Db3`, `Fs5` (`s` = sharp); `r` / `-` is a rest → `0` (a silent {@link AYNote}).
|
|
27
|
+
* Throws on a malformed name.
|
|
28
|
+
*/
|
|
29
|
+
export function noteToFreq(name) {
|
|
30
|
+
const n = name.trim().toLowerCase();
|
|
31
|
+
if (n === 'r' || n === '-' || n === '')
|
|
32
|
+
return 0;
|
|
33
|
+
const m = /^([a-g])([#sb]?)(-?\d)$/.exec(n);
|
|
34
|
+
if (!m)
|
|
35
|
+
throw new Error(`noteToFreq: bad note "${name}" (expected e.g. A5, C#4, Bb3, or r)`);
|
|
36
|
+
let semis = SEMITONE[m[1]];
|
|
37
|
+
if (m[2] === '#' || m[2] === 's')
|
|
38
|
+
semis += 1;
|
|
39
|
+
else if (m[2] === 'b')
|
|
40
|
+
semis -= 1;
|
|
41
|
+
const octave = parseInt(m[3], 10);
|
|
42
|
+
const midi = (octave + 1) * 12 + semis; // C4 = MIDI 60, A4 = 69
|
|
43
|
+
return 440 * Math.pow(2, (midi - 69) / 12);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Parses a compact note string into an {@link AYNote} array for one channel.
|
|
47
|
+
* Tokens are whitespace-separated `Note` or `Note:durMs`; `r` (or `-`) is a rest.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* seq('A4 C5:400 r:200 E5') // A4 @default, C5 @400ms, rest @200ms, E5 @default
|
|
51
|
+
*/
|
|
52
|
+
export function seq(spec, opts = {}) {
|
|
53
|
+
const defDur = opts.dur ?? 200;
|
|
54
|
+
const out = [];
|
|
55
|
+
for (const tok of spec.split(/\s+/).filter(Boolean)) {
|
|
56
|
+
const [name, durStr] = tok.split(':');
|
|
57
|
+
const note = { freq: noteToFreq(name), dur: durStr ? Number(durStr) : defDur };
|
|
58
|
+
if (opts.noise) {
|
|
59
|
+
note.noise = true;
|
|
60
|
+
if (opts.noisePeriod !== undefined)
|
|
61
|
+
note.noisePeriod = opts.noisePeriod;
|
|
62
|
+
}
|
|
63
|
+
out.push(note);
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Plays a 3-channel AY pattern on repeat — background music. Re-schedules each
|
|
69
|
+
* loop after the pattern's length (the longest channel). No-ops (returns a stop
|
|
70
|
+
* that does nothing) when there is no audio context yet or the pattern is empty.
|
|
71
|
+
*
|
|
72
|
+
* Call after the audio context is unlocked by a user gesture.
|
|
73
|
+
*/
|
|
74
|
+
export function playAYLoop(pattern) {
|
|
75
|
+
if (!getAudioContext())
|
|
76
|
+
return { stop() { } };
|
|
77
|
+
const total = (ns) => (ns ? ns.reduce((s, n) => s + n.dur, 0) : 0);
|
|
78
|
+
const loopMs = Math.max(total(pattern.a), total(pattern.b), total(pattern.c));
|
|
79
|
+
if (loopMs <= 0)
|
|
80
|
+
return { stop() { } };
|
|
81
|
+
playAY(pattern);
|
|
82
|
+
const id = setInterval(() => playAY(pattern), loopMs);
|
|
83
|
+
return {
|
|
84
|
+
stop() {
|
|
85
|
+
clearInterval(id);
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=music.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"music.js","sourceRoot":"","sources":["../src/music.ts"],"names":[],"mappings":"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"}
|