@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.
Files changed (37) hide show
  1. package/dist/{batch-CIAXVKP5.js → batch-QPSHVNDS.js} +4 -4
  2. package/dist/{batch-CIAXVKP5.js.map → batch-QPSHVNDS.js.map} +1 -1
  3. package/dist/{chunk-2NBNF6JP.js → chunk-4YTOLN3C.js} +3 -3
  4. package/dist/{chunk-2NBNF6JP.js.map → chunk-4YTOLN3C.js.map} +1 -1
  5. package/dist/chunk-V5ZSUJCA.js +354 -0
  6. package/dist/chunk-V5ZSUJCA.js.map +1 -0
  7. package/dist/{chunk-SH2INDZ2.js → chunk-VCRWS3F3.js} +3 -3
  8. package/dist/{chunk-SH2INDZ2.js.map → chunk-VCRWS3F3.js.map} +1 -1
  9. package/dist/cli.cjs +1 -1
  10. package/dist/cli.cjs.map +1 -1
  11. package/dist/cli.js +2 -2
  12. package/dist/convert/index.cjs +1 -1
  13. package/dist/convert/index.cjs.map +1 -1
  14. package/dist/convert/index.js +2 -2
  15. package/dist/index.cjs +1 -1
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.js +1 -1
  18. package/dist/player/index.cjs +58 -2
  19. package/dist/player/index.cjs.map +1 -1
  20. package/dist/player/index.d.cts +12 -158
  21. package/dist/player/index.d.ts +12 -158
  22. package/dist/player/index.js +31 -324
  23. package/dist/player/index.js.map +1 -1
  24. package/dist/schedule-DhO_Xzz4.d.cts +167 -0
  25. package/dist/schedule-PTHUONrA.d.ts +167 -0
  26. package/dist/spec/index.cjs +1 -1
  27. package/dist/spec/index.cjs.map +1 -1
  28. package/dist/spec/index.d.cts +1 -1
  29. package/dist/spec/index.d.ts +1 -1
  30. package/dist/spec/index.js +1 -1
  31. package/dist/viewer/index.cjs +684 -202
  32. package/dist/viewer/index.cjs.map +1 -1
  33. package/dist/viewer/index.d.cts +217 -64
  34. package/dist/viewer/index.d.ts +217 -64
  35. package/dist/viewer/index.js +421 -177
  36. package/dist/viewer/index.js.map +1 -1
  37. package/package.json +7 -2
@@ -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 * as tone from 'tone';
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`. Default `none` — the base export is notation only. */
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, DEFAULT_SOUNDS_BASE, INSTRUMENTS, type InstrumentDef, type InstrumentId, type MidiExportOptions, type MidiExportResult, OCTAVE_OFFSET, type PlayEvent, type PlayerOptions, type PlayerState, type RhythmMode, SALAMANDER_BASE, SAMPLED_TAALS, SHUDDHA, type Schedule, type ScheduleOptions, SwaralipiPlayer, TABLA_BPMS, TABLA_VARIATIONS, TONEJS_INSTRUMENTS_BASE, type ToneModule, buildSchedule, encodeMidi, encodeMp3, encodeWav, exportAudio, exportMidi, instrumentSampleUrl, midiToSampleName, nearestTablaBpm, normalizeBase, parseTonic, probeUrl, quantizeLoopEnd, sampleFileName, santoorUrls, subsetUrls, svaraSemitone, svaraToMidi, tablaBpms, tablaUrl };
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 };
@@ -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 * as tone from 'tone';
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`. Default `none` — the base export is notation only. */
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, DEFAULT_SOUNDS_BASE, INSTRUMENTS, type InstrumentDef, type InstrumentId, type MidiExportOptions, type MidiExportResult, OCTAVE_OFFSET, type PlayEvent, type PlayerOptions, type PlayerState, type RhythmMode, SALAMANDER_BASE, SAMPLED_TAALS, SHUDDHA, type Schedule, type ScheduleOptions, SwaralipiPlayer, TABLA_BPMS, TABLA_VARIATIONS, TONEJS_INSTRUMENTS_BASE, type ToneModule, buildSchedule, encodeMidi, encodeMp3, encodeWav, exportAudio, exportMidi, instrumentSampleUrl, midiToSampleName, nearestTablaBpm, normalizeBase, parseTonic, probeUrl, quantizeLoopEnd, sampleFileName, santoorUrls, subsetUrls, svaraSemitone, svaraToMidi, tablaBpms, tablaUrl };
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 };