@ugfoundation/swaralipi-js 0.14.0 → 0.14.2
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 +4 -0
- package/dist/{batch-D4HRATTH.js → batch-QEIW6XAA.js} +5 -5
- package/dist/{batch-D4HRATTH.js.map → batch-QEIW6XAA.js.map} +1 -1
- package/dist/{chunk-QQOC6LRA.js → chunk-6AKH2NLW.js} +6 -6
- package/dist/{chunk-QQOC6LRA.js.map → chunk-6AKH2NLW.js.map} +1 -1
- package/dist/{chunk-UV5OJYT3.js → chunk-CJI7A6AM.js} +3 -3
- package/dist/{chunk-UV5OJYT3.js.map → chunk-CJI7A6AM.js.map} +1 -1
- package/dist/{chunk-KOHSKHXI.js → chunk-K73Y46WU.js} +3 -3
- package/dist/{chunk-KOHSKHXI.js.map → chunk-K73Y46WU.js.map} +1 -1
- package/dist/{chunk-YBFM5NLW.js → chunk-WEXTZRRB.js} +29 -4
- package/dist/chunk-WEXTZRRB.js.map +1 -0
- package/dist/cli.cjs +4 -4
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +3 -3
- package/dist/convert/index.cjs +4 -4
- package/dist/convert/index.cjs.map +1 -1
- package/dist/convert/index.d.cts +1 -1
- package/dist/convert/index.d.ts +1 -1
- package/dist/convert/index.js +3 -3
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/{schedule-oJgg_bnc.d.cts → instruments-C3CbtYdm.d.ts} +171 -162
- package/dist/{schedule-DsVESieT.d.ts → instruments-CfHu4bSQ.d.cts} +171 -162
- package/dist/{lay-CXhC-HRO.d.cts → lay-Bi87MnkT.d.cts} +1 -1
- package/dist/{lay-CWlEhImP.d.ts → lay-CFLy_wd_.d.ts} +1 -1
- package/dist/player/index.cjs +163 -63
- package/dist/player/index.cjs.map +1 -1
- package/dist/player/index.d.cts +37 -17
- package/dist/player/index.d.ts +37 -17
- package/dist/player/index.js +139 -67
- package/dist/player/index.js.map +1 -1
- package/dist/spec/index.cjs +2 -2
- package/dist/spec/index.cjs.map +1 -1
- package/dist/spec/index.d.cts +12 -12
- package/dist/spec/index.d.ts +12 -12
- package/dist/spec/index.js +2 -2
- package/dist/viewer/index.cjs +127 -4
- package/dist/viewer/index.cjs.map +1 -1
- package/dist/viewer/index.d.cts +64 -4
- package/dist/viewer/index.d.ts +64 -4
- package/dist/viewer/index.js +124 -5
- package/dist/viewer/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-YBFM5NLW.js.map +0 -1
- package/dist/{schema-DZag9qkF.d.ts → schema-DyL0bMCf.d.cts} +36 -36
- package/dist/{schema-DZag9qkF.d.cts → schema-DyL0bMCf.d.ts} +36 -36
|
@@ -1,165 +1,6 @@
|
|
|
1
|
+
import { T as Taal, S as Swaralipi, N as Note } from './schema-DyL0bMCf.cjs';
|
|
2
|
+
import { L as Lay, a as LaySpeeds, T as TaalId } from './lay-Bi87MnkT.cjs';
|
|
1
3
|
import * as tone from 'tone';
|
|
2
|
-
import { S as Swaralipi, T as Taal, N as Note } from './schema-DZag9qkF.js';
|
|
3
|
-
import { T as TaalId, L as Lay, a as LaySpeeds } from './lay-CWlEhImP.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Where in the song's text each note sings, and which notes sing a stretch of it.
|
|
7
|
-
*
|
|
8
|
-
* A swaralipi's lyric row is phonetic and split into syllables (আ|বা|র্, চি|ৎ|ত,
|
|
9
|
-
* ৹ for a held syllable), and it often writes a refrain out again. So the
|
|
10
|
-
* notation's letters are aligned to the text by global alignment
|
|
11
|
-
* (Needleman–Wunsch) that may also jump to any word start, the way JumpDTW lets
|
|
12
|
-
* a score re-enter its own repeat blocks (Fremerey, Müller & Clausen, ISMIR
|
|
13
|
-
* 2010). Over gitabitan's 1827 song/notation pairs it aligns 97.9 % of the
|
|
14
|
-
* notation's letters; the rest are songs whose text is only a fragment.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
/** `part.row.note` → the `[start, end)` UTF-16 offsets of the text it sings. */
|
|
18
|
-
type LyricMap = Map<string, [number, number]>;
|
|
19
|
-
/** Play only the notes singing these `[start, end)` stretches of the text, in order. */
|
|
20
|
-
interface Excerpt {
|
|
21
|
-
lyrics: LyricMap;
|
|
22
|
-
ranges: [number, number][];
|
|
23
|
-
}
|
|
24
|
-
/** Each note of `doc` that sings a letter of `text`, with the stretch of `text` it sings. */
|
|
25
|
-
declare function alignLyrics(doc: Swaralipi, text: string): LyricMap;
|
|
26
|
-
|
|
27
|
-
/** The dynamically-imported Tone module, typed without importing it. */
|
|
28
|
-
type ToneModule = typeof tone;
|
|
29
|
-
/** A melodic instrument: a Tone.Sampler note→filename map + where to find it. */
|
|
30
|
-
interface InstrumentDef {
|
|
31
|
-
/** Human label for UIs. */
|
|
32
|
-
label: string;
|
|
33
|
-
/** Tone.Sampler `urls`: note name (`C#4`) → filename (`Cs4.mp3`). */
|
|
34
|
-
urls: Record<string, string>;
|
|
35
|
-
/** Sample directory: an absolute URL, or — when `local` — a path segment
|
|
36
|
-
* appended to the player's `soundsBaseUrl`. */
|
|
37
|
-
baseUrl: string;
|
|
38
|
-
/** `baseUrl` is relative to `soundsBaseUrl` (needs it set). */
|
|
39
|
-
local?: boolean;
|
|
40
|
-
/** Sampler release time in seconds. */
|
|
41
|
-
release?: number;
|
|
42
|
-
}
|
|
43
|
-
/** Built-in melody instrument ids (consumers may add their own via the
|
|
44
|
-
* player's `customInstruments`, so the runtime id type stays open). */
|
|
45
|
-
type InstrumentId = string;
|
|
46
|
-
/**
|
|
47
|
-
* Default host for the project's samples (santoor / tabla / tanpura /
|
|
48
|
-
* metronome) — CORS-enabled, so the player works with zero config. Override via
|
|
49
|
-
* the player's `soundsBaseUrl` to self-host. (Melody defaults to the CDN-hosted
|
|
50
|
-
* piano, so it needs no host.) Licences: see THIRD-PARTY.md.
|
|
51
|
-
*/
|
|
52
|
-
declare const DEFAULT_SOUNDS_BASE = "https://bitoron.pages.dev/audio/instruments/";
|
|
53
|
-
/** CC-BY Salamander Grand Piano (Tone's de-facto piano), CDN-hosted. */
|
|
54
|
-
declare const SALAMANDER_BASE = "https://tonejs.github.io/audio/salamander/";
|
|
55
|
-
/** CC-BY tonejs-instruments sample CDN (harmonium/violin/flute). */
|
|
56
|
-
declare const TONEJS_INSTRUMENTS_BASE = "https://nbrosowsky.github.io/tonejs-instruments/samples/";
|
|
57
|
-
/** Built-in melody instruments. santoor is local; the rest are CDN-hosted
|
|
58
|
-
* (CC-BY) so they need only network — `pianoBaseUrl`/`customInstruments`
|
|
59
|
-
* override for self-hosting. */
|
|
60
|
-
declare const INSTRUMENTS: Record<string, InstrumentDef>;
|
|
61
|
-
/** Taals with recorded tabla loops (everything else → metronome fallback). */
|
|
62
|
-
declare const SAMPLED_TAALS: ReadonlySet<TaalId>;
|
|
63
|
-
/** Available tabla loop tempos (file suffix `…<bpm>bpm.mp3`). */
|
|
64
|
-
declare const TABLA_BPMS: readonly number[];
|
|
65
|
-
/**
|
|
66
|
-
* Tabla loop variations per taal. Most taals have one unnamed loop at
|
|
67
|
-
* `tabla/<id>/`; an entry here overrides that:
|
|
68
|
-
* - `variations` lists the variation suffixes, **first = default**.
|
|
69
|
-
* A lone named variation (shashthi → `pro`, i.e. `tabla/shashthi-pro/`) IS
|
|
70
|
-
* the default; later entries are premium upsells the player never auto-selects.
|
|
71
|
-
* An empty-string entry (kehrwa → `''`) means the unnamed `tabla/<id>/` loop
|
|
72
|
-
* is the default and a named entry follows it as an upsell.
|
|
73
|
-
* - `skipBpms` are grid tempos this taal's loops were not recorded at.
|
|
74
|
-
* Consumers read this to build a variation/upsell UI; the player itself only
|
|
75
|
-
* ever plays the default (or whatever a doc's `meta.taal.variation` pins).
|
|
76
|
-
*/
|
|
77
|
-
declare const TABLA_VARIATIONS: Record<string, {
|
|
78
|
-
variations: string[];
|
|
79
|
-
skipBpms?: number[];
|
|
80
|
-
}>;
|
|
81
|
-
/** Tabla tempos actually available for a taal: the grid minus any it lacks. */
|
|
82
|
-
declare function tablaBpms(taalId: string): readonly number[];
|
|
83
|
-
/** Ensure exactly one trailing slash. */
|
|
84
|
-
declare function normalizeBase(url: string): string;
|
|
85
|
-
/** The 37 santoor samples, as a Tone.Sampler `urls` map (`C4` → `c4.mp3`). */
|
|
86
|
-
declare function santoorUrls(): Record<string, string>;
|
|
87
|
-
/**
|
|
88
|
-
* Restrict a Sampler `urls` map to just the samples needed to cover MIDI
|
|
89
|
-
* `[lo, hi]`: every sample inside the range, plus the nearest one below and
|
|
90
|
-
* above it (so Tone interpolates the edges without extrapolating). Cuts a
|
|
91
|
-
* typical song from ~37 santoor files to a handful — a big win on mobile and
|
|
92
|
-
* never worse on fast links (Tone fetches what's left in parallel). The
|
|
93
|
-
* Sampler pitch-shifts from the nearest sample, so audio is unchanged.
|
|
94
|
-
*/
|
|
95
|
-
declare function subsetUrls(urls: Record<string, string>, lo: number, hi: number): Record<string, string>;
|
|
96
|
-
/** Resolve a representative sample URL for an instrument (its first sample),
|
|
97
|
-
* used to probe availability. undefined when a local instrument has no
|
|
98
|
-
* `soundsBaseUrl` or the def has no samples. */
|
|
99
|
-
declare function instrumentSampleUrl(def: InstrumentDef, soundsBaseUrl?: string): string | undefined;
|
|
100
|
-
/**
|
|
101
|
-
* Liveness check for a sample URL: a single tiny ranged GET (one byte), the
|
|
102
|
-
* same CORS-enabled fetch Tone uses to load the buffer — so a pass means Tone
|
|
103
|
-
* can actually load it. Resolves false on any error/timeout/non-2xx, and false
|
|
104
|
-
* (no throw) when `fetch` is unavailable (Node/SSR). `Range: bytes=0-0` is a
|
|
105
|
-
* CORS-safelisted header, so no preflight.
|
|
106
|
-
*/
|
|
107
|
-
declare function probeUrl(url: string, timeoutMs?: number): Promise<boolean>;
|
|
108
|
-
/**
|
|
109
|
-
* Snap a tabla loop's end to the nearest whole beat of its measured length so a
|
|
110
|
-
* slightly-mistrimmed file still phase-locks to the melody grid instead of
|
|
111
|
-
* drifting a fraction of a beat each cycle. `spb` = seconds per beat (60/bpm).
|
|
112
|
-
* No-op for correctly trimmed loops (already an integer beat count); never
|
|
113
|
-
* extends past the buffer — a too-short file can't be repaired here.
|
|
114
|
-
*
|
|
115
|
-
* ponytail: belt-and-braces for off-spec audio; the real fix is trimming each
|
|
116
|
-
* loop to exactly `cycles × numBeats × 60/bpm` seconds at production time.
|
|
117
|
-
*/
|
|
118
|
-
declare function quantizeLoopEnd(durationSec: number, spb: number): number;
|
|
119
|
-
/** Snap an arbitrary bpm to the nearest available tabla tempo (default grid;
|
|
120
|
-
* pass a taal's `tablaBpms()` so it never snaps to a tempo that taal lacks). */
|
|
121
|
-
declare function nearestTablaBpm(bpm: number, bpms?: readonly number[]): number;
|
|
122
|
-
/** URL of the tabla loop for a taal at a (snapped) bpm, optionally a named
|
|
123
|
-
* variation (defaults to the taal's default variation — see TABLA_VARIATIONS). */
|
|
124
|
-
declare function tablaUrl(base: string, taalId: string, bpm: number, variation?: string): string;
|
|
125
|
-
declare const DRUM_KIT_BASE = "https://tonejs.github.io/audio/drum-samples/acoustic-kit/";
|
|
126
|
-
type DrumVoice = 'kick' | 'snare' | 'hihat' | 'tom1' | 'tom2' | 'tom3';
|
|
127
|
-
/**
|
|
128
|
-
* Per-beat drumset voice for one তাল cycle, following sam/tali/khaali theory:
|
|
129
|
-
* sam (cycle start) → kick, the first beat of each accented (non-khaali)
|
|
130
|
-
* vibhag → snare (the tali clap), the first beat of a khaali vibhag → closed
|
|
131
|
-
* hihat (the khaali "wave off"), every other beat → hihat (fill, keeping the
|
|
132
|
-
* kit's groove going the way a tabla's filler strokes do).
|
|
133
|
-
*/
|
|
134
|
-
declare function drumPattern(taal: Pick<Taal, 'numBeats' | 'sam' | 'bhaags' | 'khaali'>): DrumVoice[];
|
|
135
|
-
/**
|
|
136
|
-
* Fraction of the gap between two মীড় notes spent holding the source pitch
|
|
137
|
-
* before the slide begins. 0 = slide the whole way (an alaap-slow meend);
|
|
138
|
-
* 0.5 = hold half the note, then roll into the target.
|
|
139
|
-
*/
|
|
140
|
-
declare const MEEND_HOLD = 0.5;
|
|
141
|
-
/** Sampler `urls` key whose pitch is nearest `midi` (the sample to slide). */
|
|
142
|
-
declare function nearestSampleKey(urls: Record<string, string>, midi: number): string;
|
|
143
|
-
/** The same samples `createSampler` loads, as raw buffers for the glide voice. */
|
|
144
|
-
declare function createBuffers(Tone: ToneModule, def: InstrumentDef, soundsBaseUrl: string | undefined, range?: {
|
|
145
|
-
lo: number;
|
|
146
|
-
hi: number;
|
|
147
|
-
}): {
|
|
148
|
-
buffers: tone.ToneAudioBuffers;
|
|
149
|
-
urls: Record<string, string>;
|
|
150
|
-
};
|
|
151
|
-
/** One মীড় leg: the pitch to reach and the absolute time to reach it by. */
|
|
152
|
-
interface GlideLeg {
|
|
153
|
-
midi: number;
|
|
154
|
-
/** Seconds on the transport; `legs[0]` is the attack itself. */
|
|
155
|
-
at: number;
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Sound one মীড় phrase: a single attack on `legs[0]` whose pitch then slides
|
|
159
|
-
* through every following leg, ending at `endSec`. Used by both the live
|
|
160
|
-
* player and the offline export.
|
|
161
|
-
*/
|
|
162
|
-
declare function triggerGlide(Tone: ToneModule, buffers: InstanceType<ToneModule['ToneAudioBuffers']>, urls: Record<string, string>, dest: InstanceType<ToneModule['Gain']>, legs: readonly GlideLeg[], endSec: number, release?: number, hold?: number): void;
|
|
163
4
|
|
|
164
5
|
/**
|
|
165
6
|
* Pure spec-doc → playback timeline. No Tone, no audio — the player turns
|
|
@@ -356,4 +197,172 @@ declare function eventAt(events: PlayEvent[], path: string, near?: number): numb
|
|
|
356
197
|
*/
|
|
357
198
|
declare function buildSchedule(doc: Swaralipi, opts?: ScheduleOptions): Schedule;
|
|
358
199
|
|
|
359
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Where in the song's text each note sings, and which notes sing a stretch of it.
|
|
202
|
+
*
|
|
203
|
+
* A swaralipi's lyric row is phonetic and split into syllables (আ|বা|র্, চি|ৎ|ত,
|
|
204
|
+
* ৹ for a held syllable), and it often writes a refrain out again. So the
|
|
205
|
+
* notation's letters are aligned to the text by global alignment
|
|
206
|
+
* (Needleman–Wunsch) that may also jump to any word start, the way JumpDTW lets
|
|
207
|
+
* a score re-enter its own repeat blocks (Fremerey, Müller & Clausen, ISMIR
|
|
208
|
+
* 2010). Over gitabitan's 1827 song/notation pairs it aligns 97.9 % of the
|
|
209
|
+
* notation's letters; the rest are songs whose text is only a fragment.
|
|
210
|
+
*/
|
|
211
|
+
|
|
212
|
+
/** `part.row.note` → the `[start, end)` UTF-16 offsets of the text it sings. */
|
|
213
|
+
type LyricMap = Map<string, [number, number]>;
|
|
214
|
+
/** The text's lines as the events sing them, each word timed by its first note — an LRC's
|
|
215
|
+
* cues. A line sung again (a repeat) is a new cue. Words are the text's whitespace runs. */
|
|
216
|
+
declare function lyricCues(events: PlayEvent[], map: LyricMap, text: string): {
|
|
217
|
+
beat: number;
|
|
218
|
+
words: {
|
|
219
|
+
beat: number;
|
|
220
|
+
text: string;
|
|
221
|
+
}[];
|
|
222
|
+
}[];
|
|
223
|
+
/** Play only the notes singing these `[start, end)` stretches of the text, in order. */
|
|
224
|
+
interface Excerpt {
|
|
225
|
+
lyrics: LyricMap;
|
|
226
|
+
ranges: [number, number][];
|
|
227
|
+
}
|
|
228
|
+
/** Each note of `doc` that sings a letter of `text`, with the stretch of `text` it sings. */
|
|
229
|
+
declare function alignLyrics(doc: Swaralipi, text: string): LyricMap;
|
|
230
|
+
|
|
231
|
+
/** The dynamically-imported Tone module, typed without importing it. */
|
|
232
|
+
type ToneModule = typeof tone;
|
|
233
|
+
/** A melodic instrument: a Tone.Sampler note→filename map + where to find it. */
|
|
234
|
+
interface InstrumentDef {
|
|
235
|
+
/** Human label for UIs. */
|
|
236
|
+
label: string;
|
|
237
|
+
/** Tone.Sampler `urls`: note name (`C#4`) → filename (`Cs4.mp3`). */
|
|
238
|
+
urls: Record<string, string>;
|
|
239
|
+
/** Sample directory: an absolute URL, or — when `local` — a path segment
|
|
240
|
+
* appended to the player's `soundsBaseUrl`. */
|
|
241
|
+
baseUrl: string;
|
|
242
|
+
/** `baseUrl` is relative to `soundsBaseUrl` (needs it set). */
|
|
243
|
+
local?: boolean;
|
|
244
|
+
/** Sampler release time in seconds. */
|
|
245
|
+
release?: number;
|
|
246
|
+
}
|
|
247
|
+
/** Built-in melody instrument ids (consumers may add their own via the
|
|
248
|
+
* player's `customInstruments`, so the runtime id type stays open). */
|
|
249
|
+
type InstrumentId = string;
|
|
250
|
+
/**
|
|
251
|
+
* Default host for the project's samples (santoor / tabla / tanpura /
|
|
252
|
+
* metronome) — CORS-enabled, so the player works with zero config. Override via
|
|
253
|
+
* the player's `soundsBaseUrl` to self-host. (Melody defaults to the CDN-hosted
|
|
254
|
+
* piano, so it needs no host.) Licences: see THIRD-PARTY.md.
|
|
255
|
+
*/
|
|
256
|
+
declare const DEFAULT_SOUNDS_BASE = "https://bitoron.pages.dev/audio/instruments/";
|
|
257
|
+
/** CC-BY Salamander Grand Piano (Tone's de-facto piano), CDN-hosted. */
|
|
258
|
+
declare const SALAMANDER_BASE = "https://tonejs.github.io/audio/salamander/";
|
|
259
|
+
/** CC-BY tonejs-instruments sample CDN (harmonium/violin/flute). */
|
|
260
|
+
declare const TONEJS_INSTRUMENTS_BASE = "https://nbrosowsky.github.io/tonejs-instruments/samples/";
|
|
261
|
+
/** Built-in melody instruments. santoor is local; the rest are CDN-hosted
|
|
262
|
+
* (CC-BY) so they need only network — `pianoBaseUrl`/`customInstruments`
|
|
263
|
+
* override for self-hosting. */
|
|
264
|
+
declare const INSTRUMENTS: Record<string, InstrumentDef>;
|
|
265
|
+
/** Taals with recorded tabla loops (everything else → metronome fallback). */
|
|
266
|
+
declare const SAMPLED_TAALS: ReadonlySet<TaalId>;
|
|
267
|
+
/** Available tabla loop tempos (file suffix `…<bpm>bpm.mp3`). */
|
|
268
|
+
declare const TABLA_BPMS: readonly number[];
|
|
269
|
+
/**
|
|
270
|
+
* Tabla loop variations per taal. Most taals have one unnamed loop at
|
|
271
|
+
* `tabla/<id>/`; an entry here overrides that:
|
|
272
|
+
* - `variations` lists the variation suffixes, **first = default**.
|
|
273
|
+
* A lone named variation (shashthi → `pro`, i.e. `tabla/shashthi-pro/`) IS
|
|
274
|
+
* the default; later entries are premium upsells the player never auto-selects.
|
|
275
|
+
* An empty-string entry (kehrwa → `''`) means the unnamed `tabla/<id>/` loop
|
|
276
|
+
* is the default and a named entry follows it as an upsell.
|
|
277
|
+
* - `skipBpms` are grid tempos this taal's loops were not recorded at.
|
|
278
|
+
* Consumers read this to build a variation/upsell UI; the player itself only
|
|
279
|
+
* ever plays the default (or whatever a doc's `meta.taal.variation` pins).
|
|
280
|
+
*/
|
|
281
|
+
declare const TABLA_VARIATIONS: Record<string, {
|
|
282
|
+
variations: string[];
|
|
283
|
+
skipBpms?: number[];
|
|
284
|
+
}>;
|
|
285
|
+
/** Tabla tempos actually available for a taal: the grid minus any it lacks. */
|
|
286
|
+
declare function tablaBpms(taalId: string): readonly number[];
|
|
287
|
+
/** Ensure exactly one trailing slash. */
|
|
288
|
+
declare function normalizeBase(url: string): string;
|
|
289
|
+
/** The 37 santoor samples, as a Tone.Sampler `urls` map (`C4` → `c4.mp3`). */
|
|
290
|
+
declare function santoorUrls(): Record<string, string>;
|
|
291
|
+
/**
|
|
292
|
+
* Restrict a Sampler `urls` map to just the samples needed to cover MIDI
|
|
293
|
+
* `[lo, hi]`: every sample inside the range, plus the nearest one below and
|
|
294
|
+
* above it (so Tone interpolates the edges without extrapolating). Cuts a
|
|
295
|
+
* typical song from ~37 santoor files to a handful — a big win on mobile and
|
|
296
|
+
* never worse on fast links (Tone fetches what's left in parallel). The
|
|
297
|
+
* Sampler pitch-shifts from the nearest sample, so audio is unchanged.
|
|
298
|
+
*/
|
|
299
|
+
declare function subsetUrls(urls: Record<string, string>, lo: number, hi: number): Record<string, string>;
|
|
300
|
+
/** Resolve a representative sample URL for an instrument (its first sample),
|
|
301
|
+
* used to probe availability. undefined when a local instrument has no
|
|
302
|
+
* `soundsBaseUrl` or the def has no samples. */
|
|
303
|
+
declare function instrumentSampleUrl(def: InstrumentDef, soundsBaseUrl?: string): string | undefined;
|
|
304
|
+
/**
|
|
305
|
+
* Liveness check for a sample URL: a single tiny ranged GET (one byte), the
|
|
306
|
+
* same CORS-enabled fetch Tone uses to load the buffer — so a pass means Tone
|
|
307
|
+
* can actually load it. Resolves false on any error/timeout/non-2xx, and false
|
|
308
|
+
* (no throw) when `fetch` is unavailable (Node/SSR). `Range: bytes=0-0` is a
|
|
309
|
+
* CORS-safelisted header, so no preflight.
|
|
310
|
+
*/
|
|
311
|
+
declare function probeUrl(url: string, timeoutMs?: number): Promise<boolean>;
|
|
312
|
+
/**
|
|
313
|
+
* Snap a tabla loop's end to the nearest whole beat of its measured length so a
|
|
314
|
+
* slightly-mistrimmed file still phase-locks to the melody grid instead of
|
|
315
|
+
* drifting a fraction of a beat each cycle. `spb` = seconds per beat (60/bpm).
|
|
316
|
+
* No-op for correctly trimmed loops (already an integer beat count); never
|
|
317
|
+
* extends past the buffer — a too-short file can't be repaired here.
|
|
318
|
+
*
|
|
319
|
+
* ponytail: belt-and-braces for off-spec audio; the real fix is trimming each
|
|
320
|
+
* loop to exactly `cycles × numBeats × 60/bpm` seconds at production time.
|
|
321
|
+
*/
|
|
322
|
+
declare function quantizeLoopEnd(durationSec: number, spb: number): number;
|
|
323
|
+
/** Snap an arbitrary bpm to the nearest available tabla tempo (default grid;
|
|
324
|
+
* pass a taal's `tablaBpms()` so it never snaps to a tempo that taal lacks). */
|
|
325
|
+
declare function nearestTablaBpm(bpm: number, bpms?: readonly number[]): number;
|
|
326
|
+
/** URL of the tabla loop for a taal at a (snapped) bpm, optionally a named
|
|
327
|
+
* variation (defaults to the taal's default variation — see TABLA_VARIATIONS). */
|
|
328
|
+
declare function tablaUrl(base: string, taalId: string, bpm: number, variation?: string): string;
|
|
329
|
+
declare const DRUM_KIT_BASE = "https://tonejs.github.io/audio/drum-samples/acoustic-kit/";
|
|
330
|
+
type DrumVoice = 'kick' | 'snare' | 'hihat' | 'tom1' | 'tom2' | 'tom3';
|
|
331
|
+
/**
|
|
332
|
+
* Per-beat drumset voice for one তাল cycle, following sam/tali/khaali theory:
|
|
333
|
+
* sam (cycle start) → kick, the first beat of each accented (non-khaali)
|
|
334
|
+
* vibhag → snare (the tali clap), the first beat of a khaali vibhag → closed
|
|
335
|
+
* hihat (the khaali "wave off"), every other beat → hihat (fill, keeping the
|
|
336
|
+
* kit's groove going the way a tabla's filler strokes do).
|
|
337
|
+
*/
|
|
338
|
+
declare function drumPattern(taal: Pick<Taal, 'numBeats' | 'sam' | 'bhaags' | 'khaali'>): DrumVoice[];
|
|
339
|
+
/**
|
|
340
|
+
* Fraction of the gap between two মীড় notes spent holding the source pitch
|
|
341
|
+
* before the slide begins. 0 = slide the whole way (an alaap-slow meend);
|
|
342
|
+
* 0.5 = hold half the note, then roll into the target.
|
|
343
|
+
*/
|
|
344
|
+
declare const MEEND_HOLD = 0.5;
|
|
345
|
+
/** Sampler `urls` key whose pitch is nearest `midi` (the sample to slide). */
|
|
346
|
+
declare function nearestSampleKey(urls: Record<string, string>, midi: number): string;
|
|
347
|
+
/** The same samples `createSampler` loads, as raw buffers for the glide voice. */
|
|
348
|
+
declare function createBuffers(Tone: ToneModule, def: InstrumentDef, soundsBaseUrl: string | undefined, range?: {
|
|
349
|
+
lo: number;
|
|
350
|
+
hi: number;
|
|
351
|
+
}): {
|
|
352
|
+
buffers: tone.ToneAudioBuffers;
|
|
353
|
+
urls: Record<string, string>;
|
|
354
|
+
};
|
|
355
|
+
/** One মীড় leg: the pitch to reach and the absolute time to reach it by. */
|
|
356
|
+
interface GlideLeg {
|
|
357
|
+
midi: number;
|
|
358
|
+
/** Seconds on the transport; `legs[0]` is the attack itself. */
|
|
359
|
+
at: number;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Sound one মীড় phrase: a single attack on `legs[0]` whose pitch then slides
|
|
363
|
+
* through every following leg, ending at `endSec`. Used by both the live
|
|
364
|
+
* player and the offline export.
|
|
365
|
+
*/
|
|
366
|
+
declare function triggerGlide(Tone: ToneModule, buffers: InstanceType<ToneModule['ToneAudioBuffers']>, urls: Record<string, string>, dest: InstanceType<ToneModule['Gain']>, legs: readonly GlideLeg[], endSec: number, release?: number, hold?: number): void;
|
|
367
|
+
|
|
368
|
+
export { ARC_RAW_RE as A, normalizeBase as B, probeUrl as C, type DrumVoice as D, type Excerpt as E, quantizeLoopEnd as F, GRACE_STEP as G, santoorUrls as H, type InstrumentId as I, scheduleLines as J, subsetUrls as K, type Line as L, MEEND_HOLD as M, tablaBpms as N, tablaUrl as O, type PlayEvent as P, triggerGlide as Q, type Schedule as S, type TempoSegment as T, type InstrumentDef as a, DEFAULT_SOUNDS_BASE as b, DRUM_KIT_BASE as c, type GlideLeg as d, INSTRUMENTS as e, type LyricMap as f, SALAMANDER_BASE as g, SAMPLED_TAALS as h, type ScheduleOptions as i, TABLA_BPMS as j, TABLA_VARIATIONS as k, TONEJS_INSTRUMENTS_BASE as l, type ToneModule as m, alignLyrics as n, buildSchedule as o, createBuffers as p, drumPattern as q, eventAt as r, glideTargets as s, graceTouches as t, instrumentSampleUrl as u, isArcRaw as v, lyricCues as w, meendContinuations as x, nearestSampleKey as y, nearestTablaBpm as z };
|