@johnmorrisdotca/kyogijo-stadiums 0.60.1 → 0.61.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/CHANGELOG.md +9 -0
- package/README.md +2 -0
- package/catalogue.json +1 -1
- package/dist/catalogue.data.js +1 -1
- package/dist/sound-entry.d.ts +8 -0
- package/dist/sound-entry.js +6 -0
- package/dist/sound.dom.d.ts +113 -0
- package/dist/sound.dom.js +508 -0
- package/dist/sound.mix.d.ts +158 -0
- package/dist/sound.mix.js +234 -0
- package/dist/sound.sets.d.ts +70 -0
- package/dist/sound.sets.js +85 -0
- package/dist/sound.synth.d.ts +38 -0
- package/dist/sound.synth.js +303 -0
- package/dist/sound.words.d.ts +16 -0
- package/dist/sound.words.js +21 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -1
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/** A seeded generator of numbers from 0 to 1 (mulberry32): the noise is the same every time. */
|
|
2
|
+
export function seeded(seed) {
|
|
3
|
+
let a = seed >>> 0;
|
|
4
|
+
return () => {
|
|
5
|
+
a = (a + 0x6d2b79f5) >>> 0;
|
|
6
|
+
let t = a;
|
|
7
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
8
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
9
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/** Samples of noise of a colour, from a seed, between -1 and 1. */
|
|
13
|
+
export function noiseSamples(length, seed, colour = "white") {
|
|
14
|
+
const random = seeded(seed);
|
|
15
|
+
const out = new Float32Array(length);
|
|
16
|
+
// Paul Kellet's economy filter for pink; a leaky sum for brown.
|
|
17
|
+
let b0 = 0;
|
|
18
|
+
let b1 = 0;
|
|
19
|
+
let b2 = 0;
|
|
20
|
+
let last = 0;
|
|
21
|
+
for (let i = 0; i < length; i++) {
|
|
22
|
+
const white = random() * 2 - 1;
|
|
23
|
+
if (colour === "pink") {
|
|
24
|
+
b0 = 0.99765 * b0 + white * 0.099046;
|
|
25
|
+
b1 = 0.963 * b1 + white * 0.2965164;
|
|
26
|
+
b2 = 0.57 * b2 + white * 1.0526913;
|
|
27
|
+
out[i] = (b0 + b1 + b2 + white * 0.1848) * 0.2;
|
|
28
|
+
}
|
|
29
|
+
else if (colour === "brown") {
|
|
30
|
+
last = (last + 0.02 * white) / 1.02;
|
|
31
|
+
out[i] = last * 3.5;
|
|
32
|
+
}
|
|
33
|
+
else
|
|
34
|
+
out[i] = white;
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
/** Samples of hands clapping: many short bursts of noise at random moments, `density` claps a second, for `length` samples at `rate`. */
|
|
39
|
+
export function applauseSamples(length, rate, seed, density = 220) {
|
|
40
|
+
const random = seeded(seed);
|
|
41
|
+
const out = new Float32Array(length);
|
|
42
|
+
const claps = Math.round((length / rate) * density);
|
|
43
|
+
const clap = Math.round(rate * 0.012);
|
|
44
|
+
for (let c = 0; c < claps; c++) {
|
|
45
|
+
const at = Math.floor(random() * length);
|
|
46
|
+
const loud = 0.25 + random() * 0.75;
|
|
47
|
+
for (let i = 0; i < clap; i++) {
|
|
48
|
+
// A loop: a clap near the end goes on at the start, so the loop has no seam.
|
|
49
|
+
const j = (at + i) % length;
|
|
50
|
+
out[j] += (random() * 2 - 1) * loud * Math.exp((-6 * i) / clap);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
let peak = 0;
|
|
54
|
+
for (const s of out)
|
|
55
|
+
peak = Math.max(peak, Math.abs(s));
|
|
56
|
+
if (peak > 0)
|
|
57
|
+
for (let i = 0; i < length; i++)
|
|
58
|
+
out[i] /= peak;
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
/** Samples of people talking: noise whose level rises and falls with syllables, about four a second from each of many voices, summed. */
|
|
62
|
+
export function murmurSamples(length, rate, seed, voices = 24) {
|
|
63
|
+
const random = seeded(seed);
|
|
64
|
+
const noise = noiseSamples(length, seed + 1, "pink");
|
|
65
|
+
const envelope = new Float32Array(length);
|
|
66
|
+
for (let v = 0; v < voices; v++) {
|
|
67
|
+
let at = Math.floor(random() * rate * 0.3);
|
|
68
|
+
while (at < length) {
|
|
69
|
+
const syllable = Math.round(rate * (0.12 + random() * 0.16));
|
|
70
|
+
const loud = 0.3 + random() * 0.7;
|
|
71
|
+
for (let i = 0; i < syllable; i++)
|
|
72
|
+
envelope[(at + i) % length] += loud * Math.sin((Math.PI * i) / syllable);
|
|
73
|
+
at += syllable + Math.round(rate * random() * (random() < 0.15 ? 0.9 : 0.12));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
let peak = 0;
|
|
77
|
+
for (let i = 0; i < length; i++) {
|
|
78
|
+
noise[i] *= envelope[i];
|
|
79
|
+
peak = Math.max(peak, Math.abs(noise[i]));
|
|
80
|
+
}
|
|
81
|
+
if (peak > 0)
|
|
82
|
+
for (let i = 0; i < length; i++)
|
|
83
|
+
noise[i] /= peak;
|
|
84
|
+
return noise;
|
|
85
|
+
}
|
|
86
|
+
/** A room's echo as an impulse response: noise falling 60 dB over `decay` seconds, two channels a little apart. */
|
|
87
|
+
export function impulseSamples(decay, rate, seed) {
|
|
88
|
+
const length = Math.max(1, Math.round(Math.min(4, Math.max(0.2, decay)) * rate));
|
|
89
|
+
const left = noiseSamples(length, seed, "white");
|
|
90
|
+
const right = noiseSamples(length, seed + 7, "white");
|
|
91
|
+
for (let i = 0; i < length; i++) {
|
|
92
|
+
const fall = Math.exp((-6.9 * i) / length);
|
|
93
|
+
left[i] *= fall;
|
|
94
|
+
right[i] *= fall;
|
|
95
|
+
}
|
|
96
|
+
return [left, right];
|
|
97
|
+
}
|
|
98
|
+
/** A buffer of the context from samples (one channel, or two). */
|
|
99
|
+
export function bufferOf(context, channels) {
|
|
100
|
+
const buffer = context.createBuffer(channels.length, channels[0].length, context.sampleRate);
|
|
101
|
+
channels.forEach((samples, i) => buffer.getChannelData(i).set(samples));
|
|
102
|
+
return buffer;
|
|
103
|
+
}
|
|
104
|
+
/** How many seconds each made layer loops for: long enough that the loop is not heard. */
|
|
105
|
+
export const LAYER_SECONDS = 6;
|
|
106
|
+
/**
|
|
107
|
+
* How much each made layer is turned down or up so that, through its filter, it is as loud as the demo's recordings are made (an RMS of -20 dBFS; the pool's water -22, and the building's air
|
|
108
|
+
* a quiet -30): measured once in a browser by rendering each layer offline.
|
|
109
|
+
*/
|
|
110
|
+
export const LAYER_TRIM = { room: 0.22, water: 0.45, murmur: 1.58, applause: 1.41, roar: 1.12 };
|
|
111
|
+
/** The buffer a layer loops when it has no recording. */
|
|
112
|
+
export function layerBuffer(context, layer) {
|
|
113
|
+
const rate = context.sampleRate;
|
|
114
|
+
const length = Math.round(LAYER_SECONDS * rate);
|
|
115
|
+
const seed = { room: 11, water: 23, murmur: 37, applause: 41, roar: 53 }[layer];
|
|
116
|
+
const colour = layer === "room" ? "brown" : layer === "water" ? "white" : "pink";
|
|
117
|
+
const make = (s) => (layer === "murmur" ? murmurSamples(length, rate, s) : layer === "applause" ? applauseSamples(length, rate, s) : noiseSamples(length, s, colour));
|
|
118
|
+
const channels = [make(seed), make(seed + 100)];
|
|
119
|
+
for (const samples of channels)
|
|
120
|
+
for (let i = 0; i < samples.length; i++)
|
|
121
|
+
samples[i] *= LAYER_TRIM[layer];
|
|
122
|
+
return bufferOf(context, channels);
|
|
123
|
+
}
|
|
124
|
+
/** The filter that shapes a made layer: the building's low air, water's hiss, talk's middle, a crowd's voice. */
|
|
125
|
+
export function layerFilter(context, layer) {
|
|
126
|
+
const filter = context.createBiquadFilter();
|
|
127
|
+
const shape = {
|
|
128
|
+
room: ["lowpass", 260, 0.7],
|
|
129
|
+
water: ["bandpass", 2400, 0.6],
|
|
130
|
+
murmur: ["bandpass", 700, 0.55],
|
|
131
|
+
applause: ["highpass", 900, 0.7],
|
|
132
|
+
roar: ["bandpass", 620, 0.9],
|
|
133
|
+
};
|
|
134
|
+
const [type, frequency, q] = shape[layer];
|
|
135
|
+
filter.type = type;
|
|
136
|
+
filter.frequency.value = frequency;
|
|
137
|
+
filter.Q.value = q;
|
|
138
|
+
return filter;
|
|
139
|
+
}
|
|
140
|
+
/** An envelope on a gain: up in `attack`, held, then down in `release`, from `when`. */
|
|
141
|
+
function envelope(gain, when, peak, attack, hold, release) {
|
|
142
|
+
gain.setValueAtTime(0, when);
|
|
143
|
+
gain.linearRampToValueAtTime(peak, when + attack);
|
|
144
|
+
gain.setValueAtTime(peak, when + attack + hold);
|
|
145
|
+
gain.linearRampToValueAtTime(0, when + attack + hold + release);
|
|
146
|
+
return when + attack + hold + release;
|
|
147
|
+
}
|
|
148
|
+
/** An oscillator from `when` to `until`, into `into`. */
|
|
149
|
+
function tone(context, into, type, frequency, when, until) {
|
|
150
|
+
const osc = context.createOscillator();
|
|
151
|
+
osc.type = type;
|
|
152
|
+
osc.frequency.value = frequency;
|
|
153
|
+
osc.connect(into);
|
|
154
|
+
osc.start(when);
|
|
155
|
+
osc.stop(until);
|
|
156
|
+
return osc;
|
|
157
|
+
}
|
|
158
|
+
/** A burst of noise from a buffer, from `when` to `until`, into `into`. */
|
|
159
|
+
function burst(context, into, noise, when, until) {
|
|
160
|
+
const source = context.createBufferSource();
|
|
161
|
+
source.buffer = noise;
|
|
162
|
+
source.loop = true;
|
|
163
|
+
source.connect(into);
|
|
164
|
+
source.start(when);
|
|
165
|
+
source.stop(until);
|
|
166
|
+
return source;
|
|
167
|
+
}
|
|
168
|
+
/** One blast of a pea whistle: a high tone with a fast trill, and a little breath. */
|
|
169
|
+
function whistleBlast(context, out, noise, when, length) {
|
|
170
|
+
const amp = context.createGain();
|
|
171
|
+
amp.connect(out);
|
|
172
|
+
const until = envelope(amp.gain, when, 0.35, 0.015, length, 0.06);
|
|
173
|
+
const osc = tone(context, amp, "sine", 2900, when, until);
|
|
174
|
+
const trill = context.createOscillator();
|
|
175
|
+
trill.frequency.value = 28;
|
|
176
|
+
const depth = context.createGain();
|
|
177
|
+
depth.gain.value = 140;
|
|
178
|
+
trill.connect(depth);
|
|
179
|
+
depth.connect(osc.frequency);
|
|
180
|
+
trill.start(when);
|
|
181
|
+
trill.stop(until);
|
|
182
|
+
const breath = context.createBiquadFilter();
|
|
183
|
+
breath.type = "bandpass";
|
|
184
|
+
breath.frequency.value = 2900;
|
|
185
|
+
breath.Q.value = 4;
|
|
186
|
+
const breathGain = context.createGain();
|
|
187
|
+
breathGain.gain.value = 0.25;
|
|
188
|
+
breath.connect(breathGain);
|
|
189
|
+
breathGain.connect(amp);
|
|
190
|
+
burst(context, breath, noise, when, until);
|
|
191
|
+
return until;
|
|
192
|
+
}
|
|
193
|
+
/** One strike of a ring's bell: three partials that ring down. */
|
|
194
|
+
function bellStrike(context, out, when) {
|
|
195
|
+
const until = when + 1.4;
|
|
196
|
+
for (const [frequency, loud] of [[830, 0.3], [1490, 0.18], [2210, 0.12]]) {
|
|
197
|
+
const amp = context.createGain();
|
|
198
|
+
amp.gain.setValueAtTime(loud, when);
|
|
199
|
+
amp.gain.exponentialRampToValueAtTime(0.0001, until);
|
|
200
|
+
amp.connect(out);
|
|
201
|
+
tone(context, amp, "sine", frequency, when, until);
|
|
202
|
+
}
|
|
203
|
+
return until;
|
|
204
|
+
}
|
|
205
|
+
/** A crowd's vowel: noise through a filter that opens from `from` to `to` hertz, swelling and falling away. */
|
|
206
|
+
function vowel(context, out, noise, when, from, to, peak, attack, release) {
|
|
207
|
+
const filter = context.createBiquadFilter();
|
|
208
|
+
filter.type = "bandpass";
|
|
209
|
+
filter.Q.value = 1.2;
|
|
210
|
+
filter.frequency.setValueAtTime(from, when);
|
|
211
|
+
filter.frequency.linearRampToValueAtTime(to, when + attack);
|
|
212
|
+
const amp = context.createGain();
|
|
213
|
+
filter.connect(amp);
|
|
214
|
+
amp.connect(out);
|
|
215
|
+
const until = envelope(amp.gain, when, peak, attack, 0.1, release);
|
|
216
|
+
burst(context, filter, noise, when, until);
|
|
217
|
+
return until;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Make a voice in the browser at `when` on the context's clock, into `out`, from the noise of `noise` (a pink loop). Returns when it ends. The horn is one chord held, never a tune; the
|
|
221
|
+
* swell is not here, as it moves the bed's roar (the engine does it).
|
|
222
|
+
*/
|
|
223
|
+
export function makeVoice(context, voice, out, buffers, when) {
|
|
224
|
+
const noise = buffers.noise();
|
|
225
|
+
switch (voice) {
|
|
226
|
+
case "whistle":
|
|
227
|
+
return whistleBlast(context, out, noise, when, 0.45);
|
|
228
|
+
case "whistle-end": {
|
|
229
|
+
const second = whistleBlast(context, out, noise, when, 0.22) + 0.12;
|
|
230
|
+
const third = whistleBlast(context, out, noise, second, 0.22) + 0.12;
|
|
231
|
+
return whistleBlast(context, out, noise, third, 1.3);
|
|
232
|
+
}
|
|
233
|
+
case "horn": {
|
|
234
|
+
const filter = context.createBiquadFilter();
|
|
235
|
+
filter.type = "lowpass";
|
|
236
|
+
filter.frequency.value = 1100;
|
|
237
|
+
filter.Q.value = 1;
|
|
238
|
+
const amp = context.createGain();
|
|
239
|
+
filter.connect(amp);
|
|
240
|
+
amp.connect(out);
|
|
241
|
+
const until = envelope(amp.gain, when, 0.22, 0.06, 2.6, 0.6);
|
|
242
|
+
for (const frequency of [98, 98.6, 123.5, 146.8])
|
|
243
|
+
tone(context, filter, "sawtooth", frequency, when, until);
|
|
244
|
+
return until;
|
|
245
|
+
}
|
|
246
|
+
case "buzzer": {
|
|
247
|
+
const filter = context.createBiquadFilter();
|
|
248
|
+
filter.type = "lowpass";
|
|
249
|
+
filter.frequency.value = 2200;
|
|
250
|
+
const amp = context.createGain();
|
|
251
|
+
filter.connect(amp);
|
|
252
|
+
amp.connect(out);
|
|
253
|
+
const until = envelope(amp.gain, when, 0.16, 0.01, 1.3, 0.04);
|
|
254
|
+
tone(context, filter, "square", 196, when, until);
|
|
255
|
+
tone(context, filter, "sawtooth", 392, when, until);
|
|
256
|
+
return until;
|
|
257
|
+
}
|
|
258
|
+
case "bell":
|
|
259
|
+
return [0, 0.3, 0.6].reduce((end, at) => Math.max(end, bellStrike(context, out, when + at)), when);
|
|
260
|
+
case "gun": {
|
|
261
|
+
const filter = context.createBiquadFilter();
|
|
262
|
+
filter.type = "highpass";
|
|
263
|
+
filter.frequency.value = 700;
|
|
264
|
+
const amp = context.createGain();
|
|
265
|
+
filter.connect(amp);
|
|
266
|
+
amp.connect(out);
|
|
267
|
+
amp.gain.setValueAtTime(0.9, when);
|
|
268
|
+
amp.gain.exponentialRampToValueAtTime(0.0001, when + 0.35);
|
|
269
|
+
burst(context, filter, noise, when, when + 0.35);
|
|
270
|
+
const thump = context.createGain();
|
|
271
|
+
thump.gain.setValueAtTime(0.6, when);
|
|
272
|
+
thump.gain.exponentialRampToValueAtTime(0.0001, when + 0.25);
|
|
273
|
+
thump.connect(out);
|
|
274
|
+
tone(context, thump, "sine", 85, when, when + 0.25);
|
|
275
|
+
return when + 0.35;
|
|
276
|
+
}
|
|
277
|
+
case "beep": {
|
|
278
|
+
const amp = context.createGain();
|
|
279
|
+
amp.connect(out);
|
|
280
|
+
const until = envelope(amp.gain, when, 0.18, 0.005, 0.45, 0.02);
|
|
281
|
+
tone(context, amp, "square", 1000, when, until);
|
|
282
|
+
return until;
|
|
283
|
+
}
|
|
284
|
+
case "ooh":
|
|
285
|
+
return vowel(context, out, noise, when, 360, 640, 1.2, 0.35, 1.5);
|
|
286
|
+
case "cheer":
|
|
287
|
+
return vowel(context, out, noise, when, 700, 1100, 1, 0.08, 1.2);
|
|
288
|
+
case "applause": {
|
|
289
|
+
const amp = context.createGain();
|
|
290
|
+
amp.connect(out);
|
|
291
|
+
const until = envelope(amp.gain, when, 0.6, 0.25, 1.8, 1.6);
|
|
292
|
+
const source = context.createBufferSource();
|
|
293
|
+
source.buffer = buffers.applause();
|
|
294
|
+
source.loop = true;
|
|
295
|
+
const filter = layerFilter(context, "applause");
|
|
296
|
+
source.connect(filter);
|
|
297
|
+
filter.connect(amp);
|
|
298
|
+
source.start(when);
|
|
299
|
+
source.stop(until);
|
|
300
|
+
return until;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SoundBedId, SoundLevel } from "./sound.sets.ts";
|
|
2
|
+
/** The words of the sound in a language. */
|
|
3
|
+
export interface SoundWords {
|
|
4
|
+
/** The sound's toggle and its tip. */
|
|
5
|
+
sound: string;
|
|
6
|
+
soundTip: string;
|
|
7
|
+
volume: string;
|
|
8
|
+
/** The group of the crowd's levels. */
|
|
9
|
+
crowdLevel: string;
|
|
10
|
+
/** The level that follows the game. */
|
|
11
|
+
auto: string;
|
|
12
|
+
levels: Readonly<Record<SoundLevel, string>>;
|
|
13
|
+
beds: Readonly<Record<SoundBedId, string>>;
|
|
14
|
+
}
|
|
15
|
+
/** The sound's words, by language. */
|
|
16
|
+
export declare const SOUND_WORDS: Readonly<Record<"en" | "ja", SoundWords>>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** The sound's words, by language. */
|
|
2
|
+
export const SOUND_WORDS = {
|
|
3
|
+
en: {
|
|
4
|
+
sound: "Sound",
|
|
5
|
+
soundTip: "The crowd and the game's sounds, made in your browser. Off until you turn it on.",
|
|
6
|
+
volume: "Volume",
|
|
7
|
+
crowdLevel: "Crowd",
|
|
8
|
+
auto: "Follow the game",
|
|
9
|
+
levels: { quiet: "Quiet", murmur: "Murmur", engaged: "Engaged", loud: "Loud", roar: "Roar" },
|
|
10
|
+
beds: { arena: "Arena", stadium: "Open stadium", ballpark: "Ballpark", hall: "Court hall", pool: "Pool", dojo: "Dojo", ring: "Ring", track: "Track" },
|
|
11
|
+
},
|
|
12
|
+
ja: {
|
|
13
|
+
sound: "サウンド",
|
|
14
|
+
soundTip: "観客と試合の音をブラウザーの中で作ります。オンにするまで鳴りません。",
|
|
15
|
+
volume: "音量",
|
|
16
|
+
crowdLevel: "観客",
|
|
17
|
+
auto: "試合に合わせる",
|
|
18
|
+
levels: { quiet: "静か", murmur: "ざわめき", engaged: "盛り上がり", loud: "歓声", roar: "大歓声" },
|
|
19
|
+
beds: { arena: "アリーナ", stadium: "屋外スタジアム", ballpark: "野球場", hall: "体育館", pool: "プール", dojo: "道場", ring: "リング", track: "陸上競技場" },
|
|
20
|
+
},
|
|
21
|
+
};
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** The package's version: the same as package.json's, and a test holds them to each other. */
|
|
2
|
-
export declare const VERSION = "0.
|
|
2
|
+
export declare const VERSION = "0.61.0";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** The package's version: the same as package.json's, and a test holds them to each other. */
|
|
2
|
-
export const VERSION = "0.
|
|
2
|
+
export const VERSION = "0.61.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@johnmorrisdotca/kyogijo-stadiums",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.61.0",
|
|
4
4
|
"description": "Kyogijo Stadiums 競技場, 40 sports' surfaces as SVG, drawn to scale from the rulebooks: NFL, CFL and IFAF football fields, an NHL rink, an NBA court, MLB ballparks, soccer pitches, curling sheets, athletics stadiums, speed skating, short track and figure skating rinks, swimming pools, water polo fields, diving wells, artistic swimming areas, and the courts and fields of tennis, volleyball (indoor, beach and sitting), badminton, pickleball, table tennis, padel, squash, racquetball, sepak takraw, teqball, roundnet, netball, lacrosse, rugby, Australian football, Gaelic games, cricket, field hockey and handball, and the budo of judo, karate, kendo, sumo and kyudo with a dojo of tatami laid as real units, the MMA cage, with each team's name and logo on its side and the score in the middle, stands and a crowd, a pageant of flags, and a 3D view. Light and dark, accessible, a compact badge for lists, a helper for React and a custom element. Zero dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sports",
|
|
@@ -239,6 +239,11 @@
|
|
|
239
239
|
"import": "./dist/replay-entry.js",
|
|
240
240
|
"default": "./dist/replay-entry.js"
|
|
241
241
|
},
|
|
242
|
+
"./sound": {
|
|
243
|
+
"types": "./dist/sound-entry.d.ts",
|
|
244
|
+
"import": "./dist/sound-entry.js",
|
|
245
|
+
"default": "./dist/sound-entry.js"
|
|
246
|
+
},
|
|
242
247
|
"./scene": {
|
|
243
248
|
"types": "./dist/scene-entry.d.ts",
|
|
244
249
|
"import": "./dist/scene-entry.js",
|
|
@@ -371,6 +376,8 @@
|
|
|
371
376
|
"cityctx:fetch": "node scripts/fetch-cityctx.mjs",
|
|
372
377
|
"cityctx:vox": "python3.13 -I scripts/cityctx_vox.py",
|
|
373
378
|
"walk:fetch": "node scripts/fetch-walk.mjs",
|
|
379
|
+
"sounds": "node scripts/make-sounds.mjs",
|
|
380
|
+
"sounds:fetch": "node scripts/fetch-sounds.mjs",
|
|
374
381
|
"outside:cost": "node scripts/outside-cost.mjs",
|
|
375
382
|
"plateau": "node scripts/build-plateau.mjs",
|
|
376
383
|
"plateau:fetch": "node scripts/fetch-plateau.mjs",
|