@ugfoundation/swaralipi-js 0.2.0 → 0.3.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/dist/{batch-CIAXVKP5.js → batch-QPSHVNDS.js} +4 -4
- package/dist/{batch-CIAXVKP5.js.map → batch-QPSHVNDS.js.map} +1 -1
- package/dist/{chunk-2NBNF6JP.js → chunk-4YTOLN3C.js} +3 -3
- package/dist/{chunk-2NBNF6JP.js.map → chunk-4YTOLN3C.js.map} +1 -1
- package/dist/chunk-V5ZSUJCA.js +354 -0
- package/dist/chunk-V5ZSUJCA.js.map +1 -0
- package/dist/{chunk-SH2INDZ2.js → chunk-VCRWS3F3.js} +3 -3
- package/dist/{chunk-SH2INDZ2.js.map → chunk-VCRWS3F3.js.map} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/convert/index.cjs +1 -1
- package/dist/convert/index.cjs.map +1 -1
- package/dist/convert/index.js +2 -2
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/player/index.cjs +58 -2
- package/dist/player/index.cjs.map +1 -1
- package/dist/player/index.d.cts +12 -158
- package/dist/player/index.d.ts +12 -158
- package/dist/player/index.js +31 -324
- package/dist/player/index.js.map +1 -1
- package/dist/schedule-DhO_Xzz4.d.cts +167 -0
- package/dist/schedule-PTHUONrA.d.ts +167 -0
- package/dist/spec/index.cjs +1 -1
- package/dist/spec/index.cjs.map +1 -1
- package/dist/spec/index.d.cts +1 -1
- package/dist/spec/index.d.ts +1 -1
- package/dist/spec/index.js +1 -1
- package/dist/viewer/index.cjs +684 -202
- package/dist/viewer/index.cjs.map +1 -1
- package/dist/viewer/index.d.cts +217 -64
- package/dist/viewer/index.d.ts +217 -64
- package/dist/viewer/index.js +421 -177
- package/dist/viewer/index.js.map +1 -1
- package/package.json +7 -2
package/dist/player/index.d.cts
CHANGED
|
@@ -1,109 +1,12 @@
|
|
|
1
1
|
import { S as Swaralipi, O as Octave, a as SvaraLetter, N as Note } from '../schema-D3wyNRqM.cjs';
|
|
2
2
|
import { T as TaalId } from '../taals-FmEulsjY.cjs';
|
|
3
|
-
import
|
|
3
|
+
import { I as InstrumentId, a as InstrumentDef, S as Schedule } from '../schedule-DhO_Xzz4.cjs';
|
|
4
|
+
export { D as DEFAULT_SOUNDS_BASE, b as DRUM_KIT_BASE, c as DrumVoice, d as INSTRUMENTS, P as PlayEvent, e as SALAMANDER_BASE, f as SAMPLED_TAALS, g as ScheduleOptions, T as TABLA_BPMS, h as TABLA_VARIATIONS, i as TONEJS_INSTRUMENTS_BASE, j as ToneModule, k as buildSchedule, l as drumPattern, m as instrumentSampleUrl, n as nearestTablaBpm, o as normalizeBase, p as probeUrl, q as quantizeLoopEnd, s as santoorUrls, r as subsetUrls, t as tablaBpms, u as tablaUrl } from '../schedule-DhO_Xzz4.cjs';
|
|
4
5
|
import 'zod';
|
|
5
|
-
|
|
6
|
-
/** The dynamically-imported Tone module, typed without importing it. */
|
|
7
|
-
type ToneModule = typeof tone;
|
|
8
|
-
/** A melodic instrument: a Tone.Sampler note→filename map + where to find it. */
|
|
9
|
-
interface InstrumentDef {
|
|
10
|
-
/** Human label for UIs. */
|
|
11
|
-
label: string;
|
|
12
|
-
/** Tone.Sampler `urls`: note name (`C#4`) → filename (`Cs4.mp3`). */
|
|
13
|
-
urls: Record<string, string>;
|
|
14
|
-
/** Sample directory: an absolute URL, or — when `local` — a path segment
|
|
15
|
-
* appended to the player's `soundsBaseUrl`. */
|
|
16
|
-
baseUrl: string;
|
|
17
|
-
/** `baseUrl` is relative to `soundsBaseUrl` (needs it set). */
|
|
18
|
-
local?: boolean;
|
|
19
|
-
/** Sampler release time in seconds. */
|
|
20
|
-
release?: number;
|
|
21
|
-
}
|
|
22
|
-
/** Built-in melody instrument ids (consumers may add their own via the
|
|
23
|
-
* player's `customInstruments`, so the runtime id type stays open). */
|
|
24
|
-
type InstrumentId = string;
|
|
25
|
-
/**
|
|
26
|
-
* Default host for the project's samples (santoor / tabla / tanpura /
|
|
27
|
-
* metronome) — CC-BY, redistribution-verified and CORS-enabled, so the player
|
|
28
|
-
* works with zero config. Override via the player's `soundsBaseUrl` to
|
|
29
|
-
* self-host. (Melody defaults to the CDN-hosted piano, so it needs no host.)
|
|
30
|
-
*/
|
|
31
|
-
declare const DEFAULT_SOUNDS_BASE = "https://cdn.daserve.in/swaralipijs-instruments/";
|
|
32
|
-
/** CC-BY Salamander Grand Piano (Tone's de-facto piano), CDN-hosted. */
|
|
33
|
-
declare const SALAMANDER_BASE = "https://tonejs.github.io/audio/salamander/";
|
|
34
|
-
/** CC-BY tonejs-instruments sample CDN (harmonium/violin/flute). */
|
|
35
|
-
declare const TONEJS_INSTRUMENTS_BASE = "https://nbrosowsky.github.io/tonejs-instruments/samples/";
|
|
36
|
-
/** Built-in melody instruments. santoor is local; the rest are CDN-hosted
|
|
37
|
-
* (CC-BY) so they need only network — `pianoBaseUrl`/`customInstruments`
|
|
38
|
-
* override for self-hosting. */
|
|
39
|
-
declare const INSTRUMENTS: Record<string, InstrumentDef>;
|
|
40
|
-
/** Taals with recorded tabla loops (everything else → metronome fallback). */
|
|
41
|
-
declare const SAMPLED_TAALS: ReadonlySet<TaalId>;
|
|
42
|
-
/** Available tabla loop tempos (file suffix `…<bpm>bpm.mp3`). */
|
|
43
|
-
declare const TABLA_BPMS: readonly number[];
|
|
44
|
-
/**
|
|
45
|
-
* Tabla loop variations per taal. Most taals have one unnamed loop at
|
|
46
|
-
* `tabla/<id>/`; an entry here overrides that:
|
|
47
|
-
* - `variations` lists the variation suffixes, **first = default**.
|
|
48
|
-
* A lone named variation (shashthi → `pro`, i.e. `tabla/shashthi-pro/`) IS
|
|
49
|
-
* the default; later entries are premium upsells the player never auto-selects.
|
|
50
|
-
* An empty-string entry (kehrwa → `''`) means the unnamed `tabla/<id>/` loop
|
|
51
|
-
* is the default and a named entry follows it as an upsell.
|
|
52
|
-
* - `skipBpms` are grid tempos this taal's loops were not recorded at.
|
|
53
|
-
* Consumers read this to build a variation/upsell UI; the player itself only
|
|
54
|
-
* ever plays the default (or whatever a doc's `meta.taal.variation` pins).
|
|
55
|
-
*/
|
|
56
|
-
declare const TABLA_VARIATIONS: Record<string, {
|
|
57
|
-
variations: string[];
|
|
58
|
-
skipBpms?: number[];
|
|
59
|
-
}>;
|
|
60
|
-
/** Tabla tempos actually available for a taal: the grid minus any it lacks. */
|
|
61
|
-
declare function tablaBpms(taalId: string): readonly number[];
|
|
62
|
-
/** Ensure exactly one trailing slash. */
|
|
63
|
-
declare function normalizeBase(url: string): string;
|
|
64
|
-
/** The 37 santoor samples, as a Tone.Sampler `urls` map (`C4` → `c4.mp3`). */
|
|
65
|
-
declare function santoorUrls(): Record<string, string>;
|
|
66
|
-
/**
|
|
67
|
-
* Restrict a Sampler `urls` map to just the samples needed to cover MIDI
|
|
68
|
-
* `[lo, hi]`: every sample inside the range, plus the nearest one below and
|
|
69
|
-
* above it (so Tone interpolates the edges without extrapolating). Cuts a
|
|
70
|
-
* typical song from ~37 santoor files to a handful — a big win on mobile and
|
|
71
|
-
* never worse on fast links (Tone fetches what's left in parallel). The
|
|
72
|
-
* Sampler pitch-shifts from the nearest sample, so audio is unchanged.
|
|
73
|
-
*/
|
|
74
|
-
declare function subsetUrls(urls: Record<string, string>, lo: number, hi: number): Record<string, string>;
|
|
75
|
-
/** Resolve a representative sample URL for an instrument (its first sample),
|
|
76
|
-
* used to probe availability. undefined when a local instrument has no
|
|
77
|
-
* `soundsBaseUrl` or the def has no samples. */
|
|
78
|
-
declare function instrumentSampleUrl(def: InstrumentDef, soundsBaseUrl?: string): string | undefined;
|
|
79
|
-
/**
|
|
80
|
-
* Liveness check for a sample URL: a single tiny ranged GET (one byte), the
|
|
81
|
-
* same CORS-enabled fetch Tone uses to load the buffer — so a pass means Tone
|
|
82
|
-
* can actually load it. Resolves false on any error/timeout/non-2xx, and false
|
|
83
|
-
* (no throw) when `fetch` is unavailable (Node/SSR). `Range: bytes=0-0` is a
|
|
84
|
-
* CORS-safelisted header, so no preflight.
|
|
85
|
-
*/
|
|
86
|
-
declare function probeUrl(url: string, timeoutMs?: number): Promise<boolean>;
|
|
87
|
-
/**
|
|
88
|
-
* Snap a tabla loop's end to the nearest whole beat of its measured length so a
|
|
89
|
-
* slightly-mistrimmed file still phase-locks to the melody grid instead of
|
|
90
|
-
* drifting a fraction of a beat each cycle. `spb` = seconds per beat (60/bpm).
|
|
91
|
-
* No-op for correctly trimmed loops (already an integer beat count); never
|
|
92
|
-
* extends past the buffer — a too-short file can't be repaired here.
|
|
93
|
-
*
|
|
94
|
-
* ponytail: belt-and-braces for off-spec audio; the real fix is trimming each
|
|
95
|
-
* loop to exactly `cycles × numBeats × 60/bpm` seconds at production time.
|
|
96
|
-
*/
|
|
97
|
-
declare function quantizeLoopEnd(durationSec: number, spb: number): number;
|
|
98
|
-
/** Snap an arbitrary bpm to the nearest available tabla tempo (default grid;
|
|
99
|
-
* pass a taal's `tablaBpms()` so it never snaps to a tempo that taal lacks). */
|
|
100
|
-
declare function nearestTablaBpm(bpm: number, bpms?: readonly number[]): number;
|
|
101
|
-
/** URL of the tabla loop for a taal at a (snapped) bpm, optionally a named
|
|
102
|
-
* variation (defaults to the taal's default variation — see TABLA_VARIATIONS). */
|
|
103
|
-
declare function tablaUrl(base: string, taalId: string, bpm: number, variation?: string): string;
|
|
6
|
+
import 'tone';
|
|
104
7
|
|
|
105
8
|
type PlayerState = 'idle' | 'loading' | 'ready' | 'playing' | 'paused';
|
|
106
|
-
type RhythmMode = 'tabla' | 'metronome' | 'none';
|
|
9
|
+
type RhythmMode = 'tabla' | 'drums' | 'metronome' | 'none';
|
|
107
10
|
interface PlayerOptions {
|
|
108
11
|
/** Base URL for the project's samples (santoor/tabla/tanpura/metronome).
|
|
109
12
|
* Defaults to `DEFAULT_SOUNDS_BASE` (the project's CORS-enabled CDN), so the
|
|
@@ -129,7 +32,10 @@ interface PlayerOptions {
|
|
|
129
32
|
* (True sampled sitar/sarod/sarangi/esraj have no free web set; supply your
|
|
130
33
|
* own Tone.Sampler `urls` + `baseUrl` here and they slot into the picker.) */
|
|
131
34
|
customInstruments?: Record<string, InstrumentDef>;
|
|
132
|
-
/** Rhythm accompaniment. Default `tabla` (→ metronome for unsampled taals).
|
|
35
|
+
/** Rhythm accompaniment. Default `tabla` (→ metronome for unsampled taals).
|
|
36
|
+
* `drums` sequences a Western drumset (kick/snare/hihat) to the taal's
|
|
37
|
+
* sam/tali/khaali structure — a genuine "drum atlas"-style translation,
|
|
38
|
+
* not a loop; works for every taal (no per-taal sample requirement). */
|
|
133
39
|
rhythm?: RhythmMode;
|
|
134
40
|
/** Play the tanpura drone. Default true. */
|
|
135
41
|
tanpura?: boolean;
|
|
@@ -236,8 +142,9 @@ interface AudioExportOptions {
|
|
|
236
142
|
instrument?: InstrumentId;
|
|
237
143
|
/** Include the notation (melody) voice. Default true. */
|
|
238
144
|
melody?: boolean;
|
|
239
|
-
/** Rhythm accompaniment: `tabla` (→ metronome for unsampled taals),
|
|
240
|
-
* `metronome`, or `none`.
|
|
145
|
+
/** Rhythm accompaniment: `tabla` (→ metronome for unsampled taals), `drums`
|
|
146
|
+
* (Western drumset following sam/tali/khaali), `metronome`, or `none`.
|
|
147
|
+
* Default `none` — the base export is notation only. */
|
|
241
148
|
rhythm?: RhythmMode;
|
|
242
149
|
/** Taal for the rhythm: an explicit id, or `auto` (from `meta.taal`). Default
|
|
243
150
|
* `auto`. Only used when `rhythm` isn't `none`. */
|
|
@@ -288,59 +195,6 @@ declare function encodeWav(channels: Float32Array[], sampleRate: number): Uint8A
|
|
|
288
195
|
*/
|
|
289
196
|
declare function encodeMp3(channels: Float32Array[], sampleRate: number, kbps?: number): Promise<Uint8Array>;
|
|
290
197
|
|
|
291
|
-
/**
|
|
292
|
-
* Pure spec-doc → playback timeline. No Tone, no audio — the player turns
|
|
293
|
-
* this `Schedule` into Transport events, but it is fully unit-testable on its
|
|
294
|
-
* own and mirrors the viewer's spec-driven (not raw-driven) reading.
|
|
295
|
-
*
|
|
296
|
-
* Timing unit is the মাত্রা (matra / beat). One global beat cursor runs across
|
|
297
|
-
* every part and row: NLTR "systems" (rows) are wraps of one continuous line,
|
|
298
|
-
* and parts (asthayi → antara …) play back-to-back, so the music never pauses
|
|
299
|
-
* at a row or part boundary.
|
|
300
|
-
*
|
|
301
|
-
* Each audible column carries the same `data-note` path the viewer emits
|
|
302
|
-
* (`part.row.note`, note = absolute index into `row.notes`; see
|
|
303
|
-
* src/viewer/render.ts), so `SwaralipiPlayer` can drive `highlight()` directly.
|
|
304
|
-
*/
|
|
305
|
-
|
|
306
|
-
interface PlayEvent {
|
|
307
|
-
/** Onset in matra from the start of the document. */
|
|
308
|
-
beat: number;
|
|
309
|
-
/** Ring length in matra (extended by following আ-কার holds). */
|
|
310
|
-
durationBeats: number;
|
|
311
|
-
/** Pitch as MIDI, or null for a rest / আ-কার hold column. */
|
|
312
|
-
midi: number | null;
|
|
313
|
-
/** Grace-note MIDI struck just before the main attack, when present. */
|
|
314
|
-
kan: number | null;
|
|
315
|
-
/** `part.row.note` highlight path. */
|
|
316
|
-
path: string;
|
|
317
|
-
kind: 'note' | 'rest' | 'sustain';
|
|
318
|
-
}
|
|
319
|
-
interface Schedule {
|
|
320
|
-
events: PlayEvent[];
|
|
321
|
-
/** Total length in matra (the cursor's final value). */
|
|
322
|
-
totalBeats: number;
|
|
323
|
-
}
|
|
324
|
-
interface ScheduleOptions {
|
|
325
|
-
/** Tonic; accepts `C`, `C#`, `cs`… (see parseTonic). Default C. */
|
|
326
|
-
tonic?: string;
|
|
327
|
-
/** Octave of madhyam Sa (C4 = MIDI 60). Default 4. */
|
|
328
|
-
baseOctave?: number;
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Walk a document into a flat, time-ordered list of play events.
|
|
332
|
-
*
|
|
333
|
-
* - svara note → an attack at the cursor; advances by `durationMatra ?? 1`.
|
|
334
|
-
* - rest → a silent column that still advances the cursor.
|
|
335
|
-
* - sustain **with** svara (melisma) → a fresh attack (the pitch moves under
|
|
336
|
-
* a held vowel); advances.
|
|
337
|
-
* - sustain **without** svara (আ-কার hold) → no attack, but the previous
|
|
338
|
-
* audible note's ring is extended; still emitted (midi null) so the lyric
|
|
339
|
-
* column highlights; advances.
|
|
340
|
-
* - bar / bracket-only / carrier / raw-only → ignored (no event, no advance).
|
|
341
|
-
*/
|
|
342
|
-
declare function buildSchedule(doc: Swaralipi, opts?: ScheduleOptions): Schedule;
|
|
343
|
-
|
|
344
198
|
/**
|
|
345
199
|
* MIDI export — write a swaralipi doc to a downloadable Standard MIDI File.
|
|
346
200
|
*
|
|
@@ -429,4 +283,4 @@ declare function midiToSampleName(midi: number): string;
|
|
|
429
283
|
/** MIDI → santoor sample filename stem (`cs4`): lowercase, `#` → `s`. */
|
|
430
284
|
declare function sampleFileName(midi: number): string;
|
|
431
285
|
|
|
432
|
-
export { type AudioExportOptions, type AudioExportResult, type AudioFormat, type BindSheetOptions,
|
|
286
|
+
export { type AudioExportOptions, type AudioExportResult, type AudioFormat, type BindSheetOptions, InstrumentDef, InstrumentId, type MidiExportOptions, type MidiExportResult, OCTAVE_OFFSET, type PlayerOptions, type PlayerState, type RhythmMode, SHUDDHA, Schedule, SwaralipiPlayer, encodeMidi, encodeMp3, encodeWav, exportAudio, exportMidi, midiToSampleName, parseTonic, sampleFileName, svaraSemitone, svaraToMidi };
|
package/dist/player/index.d.ts
CHANGED
|
@@ -1,109 +1,12 @@
|
|
|
1
1
|
import { S as Swaralipi, O as Octave, a as SvaraLetter, N as Note } from '../schema-D3wyNRqM.js';
|
|
2
2
|
import { T as TaalId } from '../taals-FmEulsjY.js';
|
|
3
|
-
import
|
|
3
|
+
import { I as InstrumentId, a as InstrumentDef, S as Schedule } from '../schedule-PTHUONrA.js';
|
|
4
|
+
export { D as DEFAULT_SOUNDS_BASE, b as DRUM_KIT_BASE, c as DrumVoice, d as INSTRUMENTS, P as PlayEvent, e as SALAMANDER_BASE, f as SAMPLED_TAALS, g as ScheduleOptions, T as TABLA_BPMS, h as TABLA_VARIATIONS, i as TONEJS_INSTRUMENTS_BASE, j as ToneModule, k as buildSchedule, l as drumPattern, m as instrumentSampleUrl, n as nearestTablaBpm, o as normalizeBase, p as probeUrl, q as quantizeLoopEnd, s as santoorUrls, r as subsetUrls, t as tablaBpms, u as tablaUrl } from '../schedule-PTHUONrA.js';
|
|
4
5
|
import 'zod';
|
|
5
|
-
|
|
6
|
-
/** The dynamically-imported Tone module, typed without importing it. */
|
|
7
|
-
type ToneModule = typeof tone;
|
|
8
|
-
/** A melodic instrument: a Tone.Sampler note→filename map + where to find it. */
|
|
9
|
-
interface InstrumentDef {
|
|
10
|
-
/** Human label for UIs. */
|
|
11
|
-
label: string;
|
|
12
|
-
/** Tone.Sampler `urls`: note name (`C#4`) → filename (`Cs4.mp3`). */
|
|
13
|
-
urls: Record<string, string>;
|
|
14
|
-
/** Sample directory: an absolute URL, or — when `local` — a path segment
|
|
15
|
-
* appended to the player's `soundsBaseUrl`. */
|
|
16
|
-
baseUrl: string;
|
|
17
|
-
/** `baseUrl` is relative to `soundsBaseUrl` (needs it set). */
|
|
18
|
-
local?: boolean;
|
|
19
|
-
/** Sampler release time in seconds. */
|
|
20
|
-
release?: number;
|
|
21
|
-
}
|
|
22
|
-
/** Built-in melody instrument ids (consumers may add their own via the
|
|
23
|
-
* player's `customInstruments`, so the runtime id type stays open). */
|
|
24
|
-
type InstrumentId = string;
|
|
25
|
-
/**
|
|
26
|
-
* Default host for the project's samples (santoor / tabla / tanpura /
|
|
27
|
-
* metronome) — CC-BY, redistribution-verified and CORS-enabled, so the player
|
|
28
|
-
* works with zero config. Override via the player's `soundsBaseUrl` to
|
|
29
|
-
* self-host. (Melody defaults to the CDN-hosted piano, so it needs no host.)
|
|
30
|
-
*/
|
|
31
|
-
declare const DEFAULT_SOUNDS_BASE = "https://cdn.daserve.in/swaralipijs-instruments/";
|
|
32
|
-
/** CC-BY Salamander Grand Piano (Tone's de-facto piano), CDN-hosted. */
|
|
33
|
-
declare const SALAMANDER_BASE = "https://tonejs.github.io/audio/salamander/";
|
|
34
|
-
/** CC-BY tonejs-instruments sample CDN (harmonium/violin/flute). */
|
|
35
|
-
declare const TONEJS_INSTRUMENTS_BASE = "https://nbrosowsky.github.io/tonejs-instruments/samples/";
|
|
36
|
-
/** Built-in melody instruments. santoor is local; the rest are CDN-hosted
|
|
37
|
-
* (CC-BY) so they need only network — `pianoBaseUrl`/`customInstruments`
|
|
38
|
-
* override for self-hosting. */
|
|
39
|
-
declare const INSTRUMENTS: Record<string, InstrumentDef>;
|
|
40
|
-
/** Taals with recorded tabla loops (everything else → metronome fallback). */
|
|
41
|
-
declare const SAMPLED_TAALS: ReadonlySet<TaalId>;
|
|
42
|
-
/** Available tabla loop tempos (file suffix `…<bpm>bpm.mp3`). */
|
|
43
|
-
declare const TABLA_BPMS: readonly number[];
|
|
44
|
-
/**
|
|
45
|
-
* Tabla loop variations per taal. Most taals have one unnamed loop at
|
|
46
|
-
* `tabla/<id>/`; an entry here overrides that:
|
|
47
|
-
* - `variations` lists the variation suffixes, **first = default**.
|
|
48
|
-
* A lone named variation (shashthi → `pro`, i.e. `tabla/shashthi-pro/`) IS
|
|
49
|
-
* the default; later entries are premium upsells the player never auto-selects.
|
|
50
|
-
* An empty-string entry (kehrwa → `''`) means the unnamed `tabla/<id>/` loop
|
|
51
|
-
* is the default and a named entry follows it as an upsell.
|
|
52
|
-
* - `skipBpms` are grid tempos this taal's loops were not recorded at.
|
|
53
|
-
* Consumers read this to build a variation/upsell UI; the player itself only
|
|
54
|
-
* ever plays the default (or whatever a doc's `meta.taal.variation` pins).
|
|
55
|
-
*/
|
|
56
|
-
declare const TABLA_VARIATIONS: Record<string, {
|
|
57
|
-
variations: string[];
|
|
58
|
-
skipBpms?: number[];
|
|
59
|
-
}>;
|
|
60
|
-
/** Tabla tempos actually available for a taal: the grid minus any it lacks. */
|
|
61
|
-
declare function tablaBpms(taalId: string): readonly number[];
|
|
62
|
-
/** Ensure exactly one trailing slash. */
|
|
63
|
-
declare function normalizeBase(url: string): string;
|
|
64
|
-
/** The 37 santoor samples, as a Tone.Sampler `urls` map (`C4` → `c4.mp3`). */
|
|
65
|
-
declare function santoorUrls(): Record<string, string>;
|
|
66
|
-
/**
|
|
67
|
-
* Restrict a Sampler `urls` map to just the samples needed to cover MIDI
|
|
68
|
-
* `[lo, hi]`: every sample inside the range, plus the nearest one below and
|
|
69
|
-
* above it (so Tone interpolates the edges without extrapolating). Cuts a
|
|
70
|
-
* typical song from ~37 santoor files to a handful — a big win on mobile and
|
|
71
|
-
* never worse on fast links (Tone fetches what's left in parallel). The
|
|
72
|
-
* Sampler pitch-shifts from the nearest sample, so audio is unchanged.
|
|
73
|
-
*/
|
|
74
|
-
declare function subsetUrls(urls: Record<string, string>, lo: number, hi: number): Record<string, string>;
|
|
75
|
-
/** Resolve a representative sample URL for an instrument (its first sample),
|
|
76
|
-
* used to probe availability. undefined when a local instrument has no
|
|
77
|
-
* `soundsBaseUrl` or the def has no samples. */
|
|
78
|
-
declare function instrumentSampleUrl(def: InstrumentDef, soundsBaseUrl?: string): string | undefined;
|
|
79
|
-
/**
|
|
80
|
-
* Liveness check for a sample URL: a single tiny ranged GET (one byte), the
|
|
81
|
-
* same CORS-enabled fetch Tone uses to load the buffer — so a pass means Tone
|
|
82
|
-
* can actually load it. Resolves false on any error/timeout/non-2xx, and false
|
|
83
|
-
* (no throw) when `fetch` is unavailable (Node/SSR). `Range: bytes=0-0` is a
|
|
84
|
-
* CORS-safelisted header, so no preflight.
|
|
85
|
-
*/
|
|
86
|
-
declare function probeUrl(url: string, timeoutMs?: number): Promise<boolean>;
|
|
87
|
-
/**
|
|
88
|
-
* Snap a tabla loop's end to the nearest whole beat of its measured length so a
|
|
89
|
-
* slightly-mistrimmed file still phase-locks to the melody grid instead of
|
|
90
|
-
* drifting a fraction of a beat each cycle. `spb` = seconds per beat (60/bpm).
|
|
91
|
-
* No-op for correctly trimmed loops (already an integer beat count); never
|
|
92
|
-
* extends past the buffer — a too-short file can't be repaired here.
|
|
93
|
-
*
|
|
94
|
-
* ponytail: belt-and-braces for off-spec audio; the real fix is trimming each
|
|
95
|
-
* loop to exactly `cycles × numBeats × 60/bpm` seconds at production time.
|
|
96
|
-
*/
|
|
97
|
-
declare function quantizeLoopEnd(durationSec: number, spb: number): number;
|
|
98
|
-
/** Snap an arbitrary bpm to the nearest available tabla tempo (default grid;
|
|
99
|
-
* pass a taal's `tablaBpms()` so it never snaps to a tempo that taal lacks). */
|
|
100
|
-
declare function nearestTablaBpm(bpm: number, bpms?: readonly number[]): number;
|
|
101
|
-
/** URL of the tabla loop for a taal at a (snapped) bpm, optionally a named
|
|
102
|
-
* variation (defaults to the taal's default variation — see TABLA_VARIATIONS). */
|
|
103
|
-
declare function tablaUrl(base: string, taalId: string, bpm: number, variation?: string): string;
|
|
6
|
+
import 'tone';
|
|
104
7
|
|
|
105
8
|
type PlayerState = 'idle' | 'loading' | 'ready' | 'playing' | 'paused';
|
|
106
|
-
type RhythmMode = 'tabla' | 'metronome' | 'none';
|
|
9
|
+
type RhythmMode = 'tabla' | 'drums' | 'metronome' | 'none';
|
|
107
10
|
interface PlayerOptions {
|
|
108
11
|
/** Base URL for the project's samples (santoor/tabla/tanpura/metronome).
|
|
109
12
|
* Defaults to `DEFAULT_SOUNDS_BASE` (the project's CORS-enabled CDN), so the
|
|
@@ -129,7 +32,10 @@ interface PlayerOptions {
|
|
|
129
32
|
* (True sampled sitar/sarod/sarangi/esraj have no free web set; supply your
|
|
130
33
|
* own Tone.Sampler `urls` + `baseUrl` here and they slot into the picker.) */
|
|
131
34
|
customInstruments?: Record<string, InstrumentDef>;
|
|
132
|
-
/** Rhythm accompaniment. Default `tabla` (→ metronome for unsampled taals).
|
|
35
|
+
/** Rhythm accompaniment. Default `tabla` (→ metronome for unsampled taals).
|
|
36
|
+
* `drums` sequences a Western drumset (kick/snare/hihat) to the taal's
|
|
37
|
+
* sam/tali/khaali structure — a genuine "drum atlas"-style translation,
|
|
38
|
+
* not a loop; works for every taal (no per-taal sample requirement). */
|
|
133
39
|
rhythm?: RhythmMode;
|
|
134
40
|
/** Play the tanpura drone. Default true. */
|
|
135
41
|
tanpura?: boolean;
|
|
@@ -236,8 +142,9 @@ interface AudioExportOptions {
|
|
|
236
142
|
instrument?: InstrumentId;
|
|
237
143
|
/** Include the notation (melody) voice. Default true. */
|
|
238
144
|
melody?: boolean;
|
|
239
|
-
/** Rhythm accompaniment: `tabla` (→ metronome for unsampled taals),
|
|
240
|
-
* `metronome`, or `none`.
|
|
145
|
+
/** Rhythm accompaniment: `tabla` (→ metronome for unsampled taals), `drums`
|
|
146
|
+
* (Western drumset following sam/tali/khaali), `metronome`, or `none`.
|
|
147
|
+
* Default `none` — the base export is notation only. */
|
|
241
148
|
rhythm?: RhythmMode;
|
|
242
149
|
/** Taal for the rhythm: an explicit id, or `auto` (from `meta.taal`). Default
|
|
243
150
|
* `auto`. Only used when `rhythm` isn't `none`. */
|
|
@@ -288,59 +195,6 @@ declare function encodeWav(channels: Float32Array[], sampleRate: number): Uint8A
|
|
|
288
195
|
*/
|
|
289
196
|
declare function encodeMp3(channels: Float32Array[], sampleRate: number, kbps?: number): Promise<Uint8Array>;
|
|
290
197
|
|
|
291
|
-
/**
|
|
292
|
-
* Pure spec-doc → playback timeline. No Tone, no audio — the player turns
|
|
293
|
-
* this `Schedule` into Transport events, but it is fully unit-testable on its
|
|
294
|
-
* own and mirrors the viewer's spec-driven (not raw-driven) reading.
|
|
295
|
-
*
|
|
296
|
-
* Timing unit is the মাত্রা (matra / beat). One global beat cursor runs across
|
|
297
|
-
* every part and row: NLTR "systems" (rows) are wraps of one continuous line,
|
|
298
|
-
* and parts (asthayi → antara …) play back-to-back, so the music never pauses
|
|
299
|
-
* at a row or part boundary.
|
|
300
|
-
*
|
|
301
|
-
* Each audible column carries the same `data-note` path the viewer emits
|
|
302
|
-
* (`part.row.note`, note = absolute index into `row.notes`; see
|
|
303
|
-
* src/viewer/render.ts), so `SwaralipiPlayer` can drive `highlight()` directly.
|
|
304
|
-
*/
|
|
305
|
-
|
|
306
|
-
interface PlayEvent {
|
|
307
|
-
/** Onset in matra from the start of the document. */
|
|
308
|
-
beat: number;
|
|
309
|
-
/** Ring length in matra (extended by following আ-কার holds). */
|
|
310
|
-
durationBeats: number;
|
|
311
|
-
/** Pitch as MIDI, or null for a rest / আ-কার hold column. */
|
|
312
|
-
midi: number | null;
|
|
313
|
-
/** Grace-note MIDI struck just before the main attack, when present. */
|
|
314
|
-
kan: number | null;
|
|
315
|
-
/** `part.row.note` highlight path. */
|
|
316
|
-
path: string;
|
|
317
|
-
kind: 'note' | 'rest' | 'sustain';
|
|
318
|
-
}
|
|
319
|
-
interface Schedule {
|
|
320
|
-
events: PlayEvent[];
|
|
321
|
-
/** Total length in matra (the cursor's final value). */
|
|
322
|
-
totalBeats: number;
|
|
323
|
-
}
|
|
324
|
-
interface ScheduleOptions {
|
|
325
|
-
/** Tonic; accepts `C`, `C#`, `cs`… (see parseTonic). Default C. */
|
|
326
|
-
tonic?: string;
|
|
327
|
-
/** Octave of madhyam Sa (C4 = MIDI 60). Default 4. */
|
|
328
|
-
baseOctave?: number;
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Walk a document into a flat, time-ordered list of play events.
|
|
332
|
-
*
|
|
333
|
-
* - svara note → an attack at the cursor; advances by `durationMatra ?? 1`.
|
|
334
|
-
* - rest → a silent column that still advances the cursor.
|
|
335
|
-
* - sustain **with** svara (melisma) → a fresh attack (the pitch moves under
|
|
336
|
-
* a held vowel); advances.
|
|
337
|
-
* - sustain **without** svara (আ-কার hold) → no attack, but the previous
|
|
338
|
-
* audible note's ring is extended; still emitted (midi null) so the lyric
|
|
339
|
-
* column highlights; advances.
|
|
340
|
-
* - bar / bracket-only / carrier / raw-only → ignored (no event, no advance).
|
|
341
|
-
*/
|
|
342
|
-
declare function buildSchedule(doc: Swaralipi, opts?: ScheduleOptions): Schedule;
|
|
343
|
-
|
|
344
198
|
/**
|
|
345
199
|
* MIDI export — write a swaralipi doc to a downloadable Standard MIDI File.
|
|
346
200
|
*
|
|
@@ -429,4 +283,4 @@ declare function midiToSampleName(midi: number): string;
|
|
|
429
283
|
/** MIDI → santoor sample filename stem (`cs4`): lowercase, `#` → `s`. */
|
|
430
284
|
declare function sampleFileName(midi: number): string;
|
|
431
285
|
|
|
432
|
-
export { type AudioExportOptions, type AudioExportResult, type AudioFormat, type BindSheetOptions,
|
|
286
|
+
export { type AudioExportOptions, type AudioExportResult, type AudioFormat, type BindSheetOptions, InstrumentDef, InstrumentId, type MidiExportOptions, type MidiExportResult, OCTAVE_OFFSET, type PlayerOptions, type PlayerState, type RhythmMode, SHUDDHA, Schedule, SwaralipiPlayer, encodeMidi, encodeMp3, encodeWav, exportAudio, exportMidi, midiToSampleName, parseTonic, sampleFileName, svaraSemitone, svaraToMidi };
|