@k-l-lambda/lilylet 0.1.60 → 0.1.63

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.
@@ -695,13 +695,13 @@ const convertEventTerm = (eventTerm, unitLength, pendingMarks, pendingContextCha
695
695
  return undefined;
696
696
  const firstPitch = chord.pitches[0];
697
697
  // Check if rest
698
- if (firstPitch.phonet === "z" || firstPitch.phonet === "Z" || firstPitch.phonet === "x") {
698
+ if (firstPitch.phonet === "z" || firstPitch.phonet === "Z" || firstPitch.phonet === "x" || firstPitch.phonet === "y") {
699
699
  const duration = convertDuration(eventData.duration, unitLength);
700
700
  const rest = {
701
701
  type: "rest",
702
702
  duration,
703
703
  };
704
- if (firstPitch.phonet === "x") {
704
+ if (firstPitch.phonet === "x" || firstPitch.phonet === "y") {
705
705
  rest.invisible = true;
706
706
  }
707
707
  if (firstPitch.phonet === "Z") {
@@ -712,7 +712,7 @@ const convertEventTerm = (eventTerm, unitLength, pendingMarks, pendingContextCha
712
712
  return rest;
713
713
  }
714
714
  // Note or chord
715
- const pitches = chord.pitches.filter(p => p.phonet !== "z" && p.phonet !== "Z" && p.phonet !== "x").map(convertPitch);
715
+ const pitches = chord.pitches.filter(p => p.phonet !== "z" && p.phonet !== "Z" && p.phonet !== "x" && p.phonet !== "y").map(convertPitch);
716
716
  if (pitches.length === 0)
717
717
  return undefined;
718
718
  const duration = convertDuration(eventData.duration, unitLength);
@@ -781,6 +781,14 @@ const decodeTune = (tune) => {
781
781
  let tempo;
782
782
  const voiceConfigs = new Map();
783
783
  const voiceClefs = new Map();
784
+ // Pre-scan for unit length (needed for bare Q: tempo)
785
+ for (const h of headers) {
786
+ const hdr = h;
787
+ if (hdr.name === "L" && hdr.value?.numerator && hdr.value?.denominator) {
788
+ unitLength = hdr.value;
789
+ break;
790
+ }
791
+ }
784
792
  for (const h of headers) {
785
793
  if (h.comment)
786
794
  continue;
@@ -822,25 +830,45 @@ const decodeTune = (tune) => {
822
830
  tempo = { beat: beatDuration, bpm: header.value.bpm };
823
831
  }
824
832
  else if (typeof header.value === "number") {
825
- tempo = { bpm: header.value };
833
+ const beat = convertDuration({ numerator: 1, denominator: 1 }, unitLength);
834
+ tempo = { beat, bpm: header.value };
826
835
  }
827
836
  break;
828
837
  case "V": {
829
838
  const voiceValue = header.value;
830
839
  if (voiceValue) {
831
- const voiceNum = typeof voiceValue === "number" ? voiceValue :
832
- (voiceValue.name || 1);
833
- const clefStr = typeof voiceValue === "string" ? voiceValue :
834
- (voiceValue.clef || undefined);
835
- voiceConfigs.set(voiceNum, {
836
- name: voiceNum,
840
+ let voiceId;
841
+ let clefStr;
842
+ if (typeof voiceValue === "number") {
843
+ voiceId = voiceValue;
844
+ }
845
+ else if (typeof voiceValue === "string") {
846
+ voiceId = voiceValue;
847
+ }
848
+ else {
849
+ const rawClef = (voiceValue.clef || "").replace(/,+$/, "").trim();
850
+ const isKnownClef = !!convertClef(rawClef);
851
+ if (isKnownClef) {
852
+ // V:1 treble → voiceId=number, clef=treble
853
+ voiceId = voiceValue.name || 1;
854
+ clefStr = rawClef;
855
+ }
856
+ else {
857
+ // V:S clef=treble → voiceId=voiceName, clef from properties
858
+ voiceId = rawClef || voiceValue.name || 1;
859
+ const propClef = (voiceValue.properties?.clef || "").replace(/,+$/, "").trim();
860
+ clefStr = propClef || undefined;
861
+ }
862
+ }
863
+ voiceConfigs.set(voiceId, {
864
+ name: typeof voiceId === "number" ? voiceId : 1,
837
865
  clef: clefStr,
838
- properties: voiceValue.properties,
866
+ properties: voiceValue?.properties,
839
867
  });
840
868
  if (clefStr) {
841
869
  const clef = convertClef(clefStr);
842
870
  if (clef)
843
- voiceClefs.set(voiceNum, clef);
871
+ voiceClefs.set(voiceId, clef);
844
872
  }
845
873
  }
846
874
  break;