@ugfoundation/swaralipi-js 0.3.4 → 0.4.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-Y3HKAL3B.js → batch-V4X3GN4N.js} +4 -4
- package/dist/{batch-Y3HKAL3B.js.map → batch-V4X3GN4N.js.map} +1 -1
- package/dist/{chunk-AIGSKUD3.js → chunk-6QW7MSJO.js} +23 -4
- package/dist/chunk-6QW7MSJO.js.map +1 -0
- package/dist/{chunk-IG2CIUTP.js → chunk-RTKWFJFI.js} +3 -3
- package/dist/{chunk-IG2CIUTP.js.map → chunk-RTKWFJFI.js.map} +1 -1
- package/dist/{chunk-KPKD53NA.js → chunk-ZS43BDP7.js} +3 -3
- package/dist/{chunk-KPKD53NA.js.map → chunk-ZS43BDP7.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 +48 -12
- package/dist/player/index.cjs.map +1 -1
- package/dist/player/index.d.cts +2 -2
- package/dist/player/index.d.ts +2 -2
- package/dist/player/index.js +30 -13
- package/dist/player/index.js.map +1 -1
- package/dist/{schedule-dXV5cUQI.d.ts → schedule-CAns78TD.d.ts} +10 -0
- package/dist/{schedule-C2WN7YOK.d.cts → schedule-D3JyEhuO.d.cts} +10 -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 +14 -2
- package/dist/viewer/index.cjs.map +1 -1
- package/dist/viewer/index.d.cts +1 -1
- package/dist/viewer/index.d.ts +1 -1
- package/dist/viewer/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-AIGSKUD3.js.map +0 -1
package/dist/player/index.cjs
CHANGED
|
@@ -99,15 +99,25 @@ function sampleFileName(midi) {
|
|
|
99
99
|
|
|
100
100
|
// src/player/schedule.ts
|
|
101
101
|
var isSilent = (n) => n.svara === void 0 && n.rest !== true && n.sustain !== true;
|
|
102
|
+
var SAM_TICK = /^\d+[fF]$/;
|
|
102
103
|
function buildSchedule(doc, opts = {}) {
|
|
103
104
|
const tonicPc = parseTonic(opts.tonic ?? doc.meta.tonic);
|
|
104
105
|
const baseOctave = opts.baseOctave ?? 4;
|
|
105
106
|
const events = [];
|
|
106
107
|
let cursor = 0;
|
|
107
108
|
let lastPitched = -1;
|
|
109
|
+
let samBeat;
|
|
108
110
|
doc.parts.forEach((part, p) => {
|
|
109
111
|
part.rows.forEach((row, r) => {
|
|
110
112
|
row.notes.forEach((note, i) => {
|
|
113
|
+
if (samBeat === void 0 && note.above !== void 0) {
|
|
114
|
+
for (const a of note.above) {
|
|
115
|
+
if (a.raw !== void 0 && SAM_TICK.test(a.raw)) {
|
|
116
|
+
samBeat = cursor;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
111
121
|
if (note.bar !== void 0 || isSilent(note)) return;
|
|
112
122
|
const path = `${p}.${r}.${i}`;
|
|
113
123
|
const dur = note.durationMatra ?? 1;
|
|
@@ -131,7 +141,9 @@ function buildSchedule(doc, opts = {}) {
|
|
|
131
141
|
});
|
|
132
142
|
});
|
|
133
143
|
});
|
|
134
|
-
|
|
144
|
+
const numBeats = doc.meta.taal?.numBeats;
|
|
145
|
+
const pickupBeats = samBeat !== void 0 && numBeats !== void 0 && numBeats > 0 ? (numBeats - samBeat % numBeats) % numBeats : 0;
|
|
146
|
+
return { events, totalBeats: cursor, pickupBeats };
|
|
135
147
|
}
|
|
136
148
|
|
|
137
149
|
// src/player/instruments.ts
|
|
@@ -326,6 +338,13 @@ function tablaUrl(base, taalId, bpm, variation) {
|
|
|
326
338
|
const seg = tablaSeg(taalId, variation);
|
|
327
339
|
return `${normalizeBase(base)}tabla/${seg}/${seg}${bpm}bpm.mp3`;
|
|
328
340
|
}
|
|
341
|
+
var TABLA_TONIC_SEMITONE = 0;
|
|
342
|
+
function tablaShiftSemitones(tonicSemitone) {
|
|
343
|
+
const d = ((tonicSemitone - TABLA_TONIC_SEMITONE) % 12 + 12) % 12;
|
|
344
|
+
return d > 6 ? d - 12 : d;
|
|
345
|
+
}
|
|
346
|
+
var TABLA_GRAIN_SEC = 0.06;
|
|
347
|
+
var TABLA_GRAIN_OVERLAP_SEC = 0.03;
|
|
329
348
|
function metronomeUrl(base) {
|
|
330
349
|
return `${normalizeBase(base)}metronome/metro2.mp3`;
|
|
331
350
|
}
|
|
@@ -405,6 +424,7 @@ var SwaralipiPlayer = class {
|
|
|
405
424
|
#tanpura;
|
|
406
425
|
#tanpuraKey = "";
|
|
407
426
|
#metronome;
|
|
427
|
+
/** The looping tabla — a `GrainPlayer` when the tonic needs it retuned. */
|
|
408
428
|
#tabla;
|
|
409
429
|
#drums;
|
|
410
430
|
#scheduleIds = [];
|
|
@@ -762,8 +782,9 @@ var SwaralipiPlayer = class {
|
|
|
762
782
|
this.#tabla.loopEnd = quantizeLoopEnd(this.#tabla.buffer.duration, spb);
|
|
763
783
|
}
|
|
764
784
|
const draw = Tone.getDraw();
|
|
785
|
+
const shift = this.#opts.rhythm !== "none" ? schedule.pickupBeats * spb : 0;
|
|
765
786
|
for (const ev of schedule.events) {
|
|
766
|
-
const at = ev.beat * spb;
|
|
787
|
+
const at = ev.beat * spb + shift;
|
|
767
788
|
if (ev.midi !== null) {
|
|
768
789
|
const name = midiToSampleName(ev.midi);
|
|
769
790
|
const dur = Math.max(ev.durationBeats * spb, 0.05);
|
|
@@ -777,10 +798,10 @@ var SwaralipiPlayer = class {
|
|
|
777
798
|
draw.schedule(() => this.#emitHighlight(ev.path), time);
|
|
778
799
|
}, at);
|
|
779
800
|
}
|
|
780
|
-
const endAt = schedule.totalBeats * spb + spb;
|
|
801
|
+
const endAt = schedule.totalBeats * spb + shift + spb;
|
|
781
802
|
transport.scheduleOnce((time) => {
|
|
782
803
|
draw.schedule(() => this.#emitHighlight(null), time);
|
|
783
|
-
}, schedule.totalBeats * spb);
|
|
804
|
+
}, schedule.totalBeats * spb + shift);
|
|
784
805
|
transport.scheduleOnce(() => this.stop(), endAt);
|
|
785
806
|
}
|
|
786
807
|
/** Taal mode: loop one avartan forever (tabla loop / drum sequence via
|
|
@@ -840,14 +861,21 @@ var SwaralipiPlayer = class {
|
|
|
840
861
|
const wantsTabla = this.#opts.rhythm === "tabla" && taalId !== void 0 && SAMPLED_TAALS.has(taalId) && base !== void 0;
|
|
841
862
|
if (wantsTabla) {
|
|
842
863
|
const url = tablaUrl(base, taalId, nearestTablaBpm(this.bpm, tablaBpms(taalId)), this.#variation());
|
|
843
|
-
|
|
864
|
+
const shift = tablaShiftSemitones(this.#tonicSemitone());
|
|
865
|
+
this.#tabla = (shift === 0 ? new Tone.Player({ url, loop: true }) : new Tone.GrainPlayer({
|
|
866
|
+
url,
|
|
867
|
+
loop: true,
|
|
868
|
+
detune: shift * 100,
|
|
869
|
+
grainSize: TABLA_GRAIN_SEC,
|
|
870
|
+
overlap: TABLA_GRAIN_OVERLAP_SEC
|
|
871
|
+
})).connect(master);
|
|
844
872
|
this.#tabla.sync().start(0);
|
|
845
873
|
return;
|
|
846
874
|
}
|
|
847
875
|
if (this.#opts.rhythm === "drums") {
|
|
848
876
|
this.#drums ??= createDrumKit(Tone).connect(master);
|
|
849
877
|
const drums = this.#drums;
|
|
850
|
-
const taal = this.#taal ?? (taalId !== void 0 ? TAALS[taalId] : { numBeats: 4, sam: 0 }
|
|
878
|
+
const taal = this.#taal ?? (taalId !== void 0 ? TAALS[taalId] : this.#doc?.meta.taal) ?? { numBeats: 4, sam: 0 };
|
|
851
879
|
const pattern = drumPattern(taal);
|
|
852
880
|
let beat2 = 0;
|
|
853
881
|
const id2 = transport.scheduleRepeat((time) => {
|
|
@@ -861,7 +889,7 @@ var SwaralipiPlayer = class {
|
|
|
861
889
|
if (this.#opts.rhythm === "none" || base === void 0) return;
|
|
862
890
|
this.#metronome ??= createMetronome(Tone, base).connect(master);
|
|
863
891
|
const metro = this.#metronome;
|
|
864
|
-
const cycle = this.#taal?.numBeats ??
|
|
892
|
+
const cycle = this.#taal?.numBeats ?? this.#doc?.meta.taal?.numBeats ?? 4;
|
|
865
893
|
let beat = 0;
|
|
866
894
|
const id = transport.scheduleRepeat((time) => {
|
|
867
895
|
metro.volume.setValueAtTime(beat % cycle === 0 ? 0 : -8, time);
|
|
@@ -945,7 +973,8 @@ async function exportAudio(doc, options = {}) {
|
|
|
945
973
|
const spb = 60 / bpm;
|
|
946
974
|
const id = options.instrument ?? "piano";
|
|
947
975
|
const def = pickDef(id, options);
|
|
948
|
-
const
|
|
976
|
+
const shift = rhythm !== "none" ? schedule.pickupBeats * spb : 0;
|
|
977
|
+
const durationSec = Math.max(schedule.totalBeats * spb + shift + (def.release ?? 1) + fadeOutSec + 0.5, 0.5);
|
|
949
978
|
const rendered = await Tone.Offline(
|
|
950
979
|
async ({ transport }) => {
|
|
951
980
|
transport.bpm.value = bpm;
|
|
@@ -954,7 +983,7 @@ async function exportAudio(doc, options = {}) {
|
|
|
954
983
|
const sampler = createSampler(Tone, def, base, range).connect(master);
|
|
955
984
|
for (const ev of schedule.events) {
|
|
956
985
|
if (ev.midi === null) continue;
|
|
957
|
-
const at = ev.beat * spb;
|
|
986
|
+
const at = ev.beat * spb + shift;
|
|
958
987
|
const dur = Math.max(ev.durationBeats * spb, 0.05);
|
|
959
988
|
if (ev.kan !== null) {
|
|
960
989
|
const name2 = midiToSampleName(ev.kan);
|
|
@@ -967,7 +996,7 @@ async function exportAudio(doc, options = {}) {
|
|
|
967
996
|
let tabla;
|
|
968
997
|
if (rhythm === "drums" && base) {
|
|
969
998
|
const drums = createDrumKit(Tone).connect(master);
|
|
970
|
-
const taal = taalId !== void 0 ? TAALS[taalId] : { numBeats: 4, sam: 0 };
|
|
999
|
+
const taal = taalId !== void 0 ? TAALS[taalId] : doc.meta.taal ?? { numBeats: 4, sam: 0 };
|
|
971
1000
|
const pattern = drumPattern(taal);
|
|
972
1001
|
let beat = 0;
|
|
973
1002
|
transport.scheduleRepeat((time) => {
|
|
@@ -978,11 +1007,18 @@ async function exportAudio(doc, options = {}) {
|
|
|
978
1007
|
} else if (rhythm !== "none" && base) {
|
|
979
1008
|
if (usesTabla && taalId) {
|
|
980
1009
|
const url = tablaUrl(base, taalId, bpm, variation);
|
|
981
|
-
|
|
1010
|
+
const semis = tablaShiftSemitones(parseTonic(options.tonic ?? doc.meta.tonic));
|
|
1011
|
+
tabla = (semis === 0 ? new Tone.Player({ url, loop: true }) : new Tone.GrainPlayer({
|
|
1012
|
+
url,
|
|
1013
|
+
loop: true,
|
|
1014
|
+
detune: semis * 100,
|
|
1015
|
+
grainSize: TABLA_GRAIN_SEC,
|
|
1016
|
+
overlap: TABLA_GRAIN_OVERLAP_SEC
|
|
1017
|
+
})).connect(master);
|
|
982
1018
|
tabla.sync().start(0);
|
|
983
1019
|
} else {
|
|
984
1020
|
const metro = createMetronome(Tone, base).connect(master);
|
|
985
|
-
const cycle = taalId !== void 0 ? TAALS[taalId].numBeats : 4;
|
|
1021
|
+
const cycle = taalId !== void 0 ? TAALS[taalId].numBeats : doc.meta.taal?.numBeats ?? 4;
|
|
986
1022
|
let beat = 0;
|
|
987
1023
|
transport.scheduleRepeat((time) => {
|
|
988
1024
|
metro.volume.setValueAtTime(beat % cycle === 0 ? 0 : -8, time);
|