@real-music-packages/web-core 0.24.1 → 0.26.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real-music-packages/web-core",
3
- "version": "0.24.1",
3
+ "version": "0.26.0",
4
4
  "description": "Shared music-theory + audio primitives for the music-suite web apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,31 +0,0 @@
1
- // src/notes.ts
2
- var NOTE_NAMES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
3
- var NOTE_NAMES_FLAT = ["C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B"];
4
- var LETTER_TO_INDEX = { C: 0, D: 2, E: 4, F: 5, G: 7, A: 9, B: 11 };
5
- function noteNameToIndex(note) {
6
- const letter = note[0]?.toUpperCase();
7
- let index = LETTER_TO_INDEX[letter];
8
- if (index === void 0) throw new Error(`Invalid note name: ${note}`);
9
- for (const ch of note.slice(1)) {
10
- if (ch === "#") index += 1;
11
- else if (ch === "b") index -= 1;
12
- }
13
- return (index % 12 + 12) % 12;
14
- }
15
- function pitchClass(midi) {
16
- return (midi % 12 + 12) % 12;
17
- }
18
- function midiToNoteName(midi, useFlats = false) {
19
- const names = useFlats ? NOTE_NAMES_FLAT : NOTE_NAMES;
20
- const octave = Math.floor(midi / 12) - 1;
21
- return `${names[pitchClass(midi)]}${octave}`;
22
- }
23
-
24
- export {
25
- NOTE_NAMES,
26
- NOTE_NAMES_FLAT,
27
- noteNameToIndex,
28
- pitchClass,
29
- midiToNoteName
30
- };
31
- //# sourceMappingURL=chunk-25RUSM2X.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/notes.ts"],"sourcesContent":["export const NOTE_NAMES = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'] as const;\nexport const NOTE_NAMES_FLAT = ['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B'] as const;\n\nconst LETTER_TO_INDEX: Record<string, number> = { C: 0, D: 2, E: 4, F: 5, G: 7, A: 9, B: 11 };\n\n/** Note name (e.g. \"C\", \"C#\", \"Db\", \"Cb\") → pitch class 0..11. */\nexport function noteNameToIndex(note: string): number {\n const letter = note[0]?.toUpperCase();\n let index = LETTER_TO_INDEX[letter];\n if (index === undefined) throw new Error(`Invalid note name: ${note}`);\n for (const ch of note.slice(1)) {\n if (ch === '#') index += 1;\n else if (ch === 'b') index -= 1;\n }\n return ((index % 12) + 12) % 12;\n}\n\n/** MIDI number → pitch class 0..11. */\nexport function pitchClass(midi: number): number {\n return ((midi % 12) + 12) % 12;\n}\n\n/** MIDI → note name with octave, e.g. 61 → \"C#4\" (or \"Db4\" with useFlats). */\nexport function midiToNoteName(midi: number, useFlats = false): string {\n const names = useFlats ? NOTE_NAMES_FLAT : NOTE_NAMES;\n const octave = Math.floor(midi / 12) - 1;\n return `${names[pitchClass(midi)]}${octave}`;\n}\n"],"mappings":";AAAO,IAAM,aAAa,CAAC,KAAK,MAAM,KAAK,MAAM,KAAK,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,GAAG;AACnF,IAAM,kBAAkB,CAAC,KAAK,MAAM,KAAK,MAAM,KAAK,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,GAAG;AAE/F,IAAM,kBAA0C,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG;AAGrF,SAAS,gBAAgB,MAAsB;AACpD,QAAM,SAAS,KAAK,CAAC,GAAG,YAAY;AACpC,MAAI,QAAQ,gBAAgB,MAAM;AAClC,MAAI,UAAU,OAAW,OAAM,IAAI,MAAM,sBAAsB,IAAI,EAAE;AACrE,aAAW,MAAM,KAAK,MAAM,CAAC,GAAG;AAC9B,QAAI,OAAO,IAAK,UAAS;AAAA,aAChB,OAAO,IAAK,UAAS;AAAA,EAChC;AACA,UAAS,QAAQ,KAAM,MAAM;AAC/B;AAGO,SAAS,WAAW,MAAsB;AAC/C,UAAS,OAAO,KAAM,MAAM;AAC9B;AAGO,SAAS,eAAe,MAAc,WAAW,OAAe;AACrE,QAAM,QAAQ,WAAW,kBAAkB;AAC3C,QAAM,SAAS,KAAK,MAAM,OAAO,EAAE,IAAI;AACvC,SAAO,GAAG,MAAM,WAAW,IAAI,CAAC,CAAC,GAAG,MAAM;AAC5C;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/scales.ts","../src/enharmonic.ts"],"sourcesContent":["import { noteNameToIndex } from './notes';\n\nexport const MAJOR_SCALE_INTERVALS = [0, 2, 4, 5, 7, 9, 11] as const;\nexport const ALL_KEYS = ['C', 'G', 'D', 'A', 'E', 'B', 'F#', 'F', 'Bb', 'Eb', 'Ab', 'Db'] as const;\n\n/**\n * Get MIDI note number for a scale degree in a given key.\n * Ported verbatim from RET src/lib/audio/scales.ts.\n * NOTE: RET uses octave*12 (not (octave+1)*12), so getMidiNote(1,'C',4)=48,\n * not 60. This is RET's established convention — consumers must account for it.\n */\nexport function getMidiNote(degree: number, key: string, octave = 4): number {\n const rootIndex = noteNameToIndex(key);\n const actualDegree = ((degree - 1) % 7 + 7) % 7;\n const octaveShift = Math.floor((degree - 1) / 7);\n const semitones = MAJOR_SCALE_INTERVALS[actualDegree];\n return rootIndex + semitones + ((octave + octaveShift) * 12);\n}\n\n/**\n * Get the scale degree (1-7) for a MIDI note in a key, or null if not in scale.\n * Ported verbatim from RET src/lib/audio/scales.ts.\n */\nexport function getScaleDegree(midiNote: number, key: string): number | null {\n const rootIndex = noteNameToIndex(key);\n const noteInOctave = ((midiNote % 12) - rootIndex + 12) % 12;\n const degreeIndex = (MAJOR_SCALE_INTERVALS as readonly number[]).indexOf(noteInOctave);\n return degreeIndex !== -1 ? degreeIndex + 1 : null;\n}\n\n/**\n * Check if a MIDI note is in the given key.\n */\nexport function isInScale(midiNote: number, key: string): boolean {\n return getScaleDegree(midiNote, key) !== null;\n}\n\n/**\n * Get stability category for a scale degree.\n * Ported verbatim from RET src/lib/audio/scales.ts.\n */\nexport function getStability(degree: number): 'stable' | 'lessStable' | 'unstable' | null {\n if ([1, 3, 5].includes(degree)) return 'stable';\n if ([2, 4, 6].includes(degree)) return 'lessStable';\n if (degree === 7) return 'unstable';\n return null;\n}\n","/** Keys conventionally spelled with flats (RET's key-name model). */\nexport const KEYS_PREFER_FLATS = ['F', 'Bb', 'Eb', 'Ab', 'Db', 'Gb'] as const;\n\n/** Whether to use flat spellings for a key given by name (e.g. \"Eb\"). */\nexport function useFlatsForKeyName(key: string): boolean {\n return (KEYS_PREFER_FLATS as readonly string[]).includes(key);\n}\n\n/**\n * Whether to use flat spellings for a key given by its key-signature \"fifths\"\n * value (Stave's model: -7..+7, negative = flat keys). 0 (C) and positive\n * (sharp keys) use sharps.\n */\nexport function useFlatsForKeyFifths(fifths: number): boolean {\n return fifths < 0;\n}\n"],"mappings":";;;;;AAEO,IAAM,wBAAwB,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE;AACnD,IAAM,WAAW,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK,MAAM,MAAM,MAAM,IAAI;AAQjF,SAAS,YAAY,QAAgB,KAAa,SAAS,GAAW;AAC3E,QAAM,YAAY,gBAAgB,GAAG;AACrC,QAAM,iBAAiB,SAAS,KAAK,IAAI,KAAK;AAC9C,QAAM,cAAc,KAAK,OAAO,SAAS,KAAK,CAAC;AAC/C,QAAM,YAAY,sBAAsB,YAAY;AACpD,SAAO,YAAY,aAAc,SAAS,eAAe;AAC3D;AAMO,SAAS,eAAe,UAAkB,KAA4B;AAC3E,QAAM,YAAY,gBAAgB,GAAG;AACrC,QAAM,gBAAiB,WAAW,KAAM,YAAY,MAAM;AAC1D,QAAM,cAAe,sBAA4C,QAAQ,YAAY;AACrF,SAAO,gBAAgB,KAAK,cAAc,IAAI;AAChD;AAKO,SAAS,UAAU,UAAkB,KAAsB;AAChE,SAAO,eAAe,UAAU,GAAG,MAAM;AAC3C;AAMO,SAAS,aAAa,QAA6D;AACxF,MAAI,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,MAAM,EAAG,QAAO;AACvC,MAAI,CAAC,GAAG,GAAG,CAAC,EAAE,SAAS,MAAM,EAAG,QAAO;AACvC,MAAI,WAAW,EAAG,QAAO;AACzB,SAAO;AACT;;;AC7CO,IAAM,oBAAoB,CAAC,KAAK,MAAM,MAAM,MAAM,MAAM,IAAI;AAG5D,SAAS,mBAAmB,KAAsB;AACvD,SAAQ,kBAAwC,SAAS,GAAG;AAC9D;AAOO,SAAS,qBAAqB,QAAyB;AAC5D,SAAO,SAAS;AAClB;","names":[]}