### Live Example Output Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/rhythm.md Demonstration of rhythm functions in a live environment. ```ts log(durationName("q."), "=", wholeNotes("q."), "whole notes"); log("7/8 groups as", beatGrouping("7/8")); log(tickToPosition(1500, "6/8")); ``` -------------------------------- ### Live interval demonstration Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/intervals.md Example showing interval parsing, transposition, and playback. ```js const fifth = parseInterval("P5"); log(new Note("C4").transpose(fifth).toString()); log(intervalName(intervalFromSemitones(10))); play(["C4", new Note("C4").transpose(fifth)]); ``` -------------------------------- ### Install MusicTheoryJS Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/getting-started.md Use your preferred package manager to add the library to your project. ```bash bun add musictheoryjs # npm i musictheoryjs · pnpm add musictheoryjs · yarn add musictheoryjs ``` -------------------------------- ### Development workflow commands Source: https://github.com/zachacious/musictheoryjs/blob/master/README.md Standard commands for installing dependencies, running tests, type checking, linting, and building the package. ```bash bun install bun test # test suite bun run typecheck bun run lint bun run build # ESM + CJS + .d.ts bun run e2e # exercises the built package (ESM and CJS) ``` -------------------------------- ### Install AI Agent Skill Source: https://github.com/zachacious/musictheoryjs/blob/master/README.md Commands to install the AI agent skill for better compatibility with the v3 API. ```bash cp -r node_modules/musictheoryjs/skills/musictheoryjs .claude/skills/ ``` ```bash npx degit Zachacious/MusicTheoryJS/skills/musictheoryjs .claude/skills/musictheoryjs ``` -------------------------------- ### Note and Interval Operations Source: https://github.com/zachacious/musictheoryjs/blob/master/skills/musictheoryjs/SKILL.md Examples of creating notes, transposing them, and calculating intervals using the musictheoryjs library. ```APIDOC ## Note and Interval API ### Description Methods for creating, transposing, and analyzing musical notes and intervals. ### Usage - `note(string)`: Create a note from a string (e.g., "C4"). - `Note.fromMidi(number, accidental)`: Create a note from a MIDI number. - `note.transpose(interval)`: Transpose a note by a given interval or semitone count. - `note.equals(other)`: Check for exact equality. - `note.isEnharmonic(other)`: Check if two notes are enharmonically equivalent. - `note.flatten()` / `note.sharpen()`: Adjust note accidentals. ### Example ```ts import { Note, note, interval, intervalName, transposeNotes } from "musictheoryjs"; note("C4").transpose("P5").toString(); // => "G4" note("C4").transpose(3).toString(); // => "Eb4" Note.fromMidi(61, "flat").toString(); // => "Db4" ``` ``` -------------------------------- ### Install Agent Skill locally Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/ai.md Copies the Agent Skill from the installed npm package into the local Claude project directory. ```bash cp -r node_modules/musictheoryjs/skills/musictheoryjs .claude/skills/ ``` -------------------------------- ### Interactive Rhythm Examples Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/patterns.md Demonstrates various rhythm manipulation functions including rotation, onset conversion, and hexadecimal representation. ```ts const tresillo = euclideanRhythm(8, 3); log("tresillo ", tresillo.join("")); log("onsets ", rhythmToOnsets(tresillo)); log("rotated 2 ", rotateRhythm(tresillo, 2).join("")); log("clave hex ", rhythmToHex(euclideanRhythm(16, 5))); log("cinquillo ", euclideanRhythm(8, 5).join("")); ``` -------------------------------- ### Interactive library usage Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/getting-started.md Example of using the library in an interactive environment with log and play functions. ```typescript const scale = Scale.from("D4", "dorian"); log(scale.noteNames()); log(Chord.from("Dm7").noteNames()); play(scale); ``` -------------------------------- ### Fetch Agent Skill via degit Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/ai.md Downloads the Agent Skill directly from the repository without requiring a full npm package installation. ```bash npx degit Zachacious/MusicTheoryJS/skills/musictheoryjs .claude/skills/musictheoryjs ``` -------------------------------- ### Basic Music Theory Operations Source: https://github.com/zachacious/musictheoryjs/blob/master/README.md Examples of using Scale, Chord, Key, and Note classes to perform common music theory calculations. ```ts import { Note, Scale, Chord, Key, interval } from "musictheoryjs"; Scale.from("C4", "major").noteNames(); // ["C4","D4","E4","F4","G4","A4","B4"] Chord.from("Cmaj7").noteNames(); // ["C4","E4","G4","B4"] Key.major("C").progression("ii7 V7 Imaj7"); // [Dm7, G7, Cmaj7] new Note("C4").transpose(interval(5, "P")).toString(); // "G4" ``` -------------------------------- ### Initialization Comparison Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/migration.md v3 removes the need for manual table building required in 2.x. ```js // 2.x import { buildTables, Note } from "musictheoryjs"; buildTables(); // required before string initializers were fast ``` ```ts // v3 — just import and go import { Note } from "musictheoryjs"; new Note("D4").toString(); // => "D4" ``` -------------------------------- ### Analyze and play chords live Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/chords.md Demonstrates creating a chord object, retrieving note names, applying a drop 2 voicing, and playing the result. ```js const chord = Chord.from("Cmaj9"); log(chord.noteNames()); log("drop 2:", drop2(chord).map(String)); play(chord); ``` -------------------------------- ### Import Scala files Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/tuning.md Parse Scala (.scl) format strings into tuning objects. ```ts import { scalaTuning } from "musictheoryjs"; const scl = ` ! example.scl Example just major scale 7 9/8 5/4 4/3 3/2 5/3 15/8 2/1 `; const tuning = scalaTuning(scl); tuning.size; // 7 tuning.centsForDegree(4); // 701.955 (the 3/2) ``` -------------------------------- ### Define a NoteStream Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/analysis.md Create a collection of NoteEvent objects with pitch, start time, and duration to serve as input for analysis. ```ts import type { NoteEvent, NoteStream } from "musictheoryjs"; import { Note } from "musictheoryjs"; const stream: NoteStream = [ { pitch: new Note("C4"), start: 0, duration: 1, velocity: 100 }, { pitch: new Note("E4"), start: 0, duration: 1 }, { pitch: new Note("G4"), start: 0, duration: 1 }, ]; ``` -------------------------------- ### Accessing Historical Western Tunings Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/tuning.md Demonstrates how to import and use Pythagorean, quarter-comma meantone, and Just Intonation tunings to calculate cents and frequencies. ```ts import { pythagorean, quarterCommaMeantone, justIntonation } from "musictheoryjs"; pythagorean().centsForDegree(7); // 701.955 (pure fifth) quarterCommaMeantone().centsForDegree(4); // 386.31 (pure major third) justIntonation().centsForDegree(4); // 386.31 (5/4) frequencyOfNote(new Note("E4"), justIntonation()); // pure third above C ``` -------------------------------- ### Basic usage of Notes, Scales, and Chords Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/getting-started.md Demonstrates creating notes, generating scales, and parsing chord symbols. ```typescript import { Note, Scale, Chord } from "musictheoryjs"; // Notes know their letter, accidental, octave, MIDI number, and frequency. new Note("C4").midi; // 60 // Scales come out spelled correctly. Scale.from("C4", "major").noteNames(); // ["C4", "D4", "E4", "F4", "G4", "A4", "B4"] // Chords parse from the symbols you'd actually type. Chord.from("Cmaj7").noteNames(); // ["C4", "E4", "G4", "B4"] ``` -------------------------------- ### Play chord progressions Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/keys.md Create and play a chord progression within a specific key using the live execution environment. ```ts const key = Key.major("Bb"); const chords = key.progression("ii7 V7 Imaj7"); log(chords.map(String)); play( chords.flatMap((c, i) => c.notes.map((n) => ({ pitch: n, start: i * 0.8, duration: 0.75 })) ) ); ``` -------------------------------- ### Expand song form into a timeline Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/sequencing.md Uses songForm to map a letter scheme to specific melody parts and calculate section start times. ```ts import { melody, songForm } from "musictheoryjs"; const A = melody(["C4", "E4", "G4", "E4"], "q"); const B = melody(["F4", "A4", "F4", "D4"], "q"); const tune = songForm("AABA", { A, B }); tune.sections.map((s) => s.start); // [0, 4, 8, 12] tune.stream.length; // 16 ``` -------------------------------- ### Utilizing Non-Western Tuning Presets Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/tuning.md Shows how to access maqamat, ragas, and gamelan tuning presets as standard Tuning objects. ```ts import { maqamTuning, ragaTuning, slendro, pelog, scaleFromTuning } from "musictheoryjs"; maqamTuning("rast").centsForDegree(2); // 350 — the neutral third ragaTuning("bhairav"); // thaat as 5-limit just ratios slendro(); // five near-equal gamelan steps scaleFromTuning(pelog(), { frequency: 275 }, true); ``` -------------------------------- ### Slice musical streams Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/sequencing.md Cuts a time window from a stream. Events crossing the edge are truncated, and the result defaults to starting at beat 0. ```ts import { melody, sliceStream, loopStream } from "musictheoryjs"; const line = melody(["C4", "D4", "E4", "F4"], "q"); sliceStream(line, 1, 3).map((e) => e.pitch.toString()); // ["D4", "E4"] loopStream(sliceStream(line, 2), 2).map((e) => e.start); // [0, 1, 2, 3] ``` -------------------------------- ### Migrating Scale Operations to v3 Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/migration.md Demonstrates the transition from v2.x class-based scale instantiation and methods to the v3 static factory pattern and mode functions. ```ts import { Scale, mode } from "musictheoryjs"; const scale = Scale.from("C5", "major"); scale.noteNames(); // => ["C5", "D5", "E5", "F5", "G5", "A5", "B5"] scale.degree(3).toString(); // => "E5" // 2.x: scale.dorian() / scale.shift(1) — the dorian pattern on the same key Scale.from(scale.tonic, "dorian").noteNames()[2]; // => "Eb5" // 2.x: scale.relativeMinor() mode(scale, 6).noteNames()[0]; // => "A5" // 2.x: new Scale({ key: 0, octave: 4, template: [...] }) Scale.fromSemitones("C4", [0, 2, 4, 5, 7, 9, 11]).noteNames()[6]; // => "B4" ``` -------------------------------- ### Compare tuning objects and names Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/tuning.md Demonstrate that tuning names are interchangeable with tuning objects in library functions. ```ts import { frequencyOfNote, parseNote, justIntonation } from "musictheoryjs"; frequencyOfNote(parseNote("E4"), "Just") === frequencyOfNote(parseNote("E4"), justIntonation()); // true ``` -------------------------------- ### Rotate rhythm patterns Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/patterns.md Use rotateRhythm to shift the starting point of a pattern. Positive values rotate left, negative values rotate right, and values wrap around the grid length. ```ts import { euclideanRhythm, rotateRhythm } from "musictheoryjs"; const tresillo = euclideanRhythm(8, 3); // [1,0,0,1,0,0,1,0] rotateRhythm(tresillo, 2); // [0,1,0,0,1,0,1,0] rotateRhythm(tresillo, -1); // [0,1,0,0,1,0,0,1] ``` -------------------------------- ### Realize a tuning as a scale Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/tuning.md Generate a period of a tuning as a collection of degrees, cents, and frequencies using scaleFromTuning. ```ts import { scaleFromTuning, equalTemperament } from "musictheoryjs"; scaleFromTuning(equalTemperament(24)); // [{ degree: 0, cents: 0, frequency: 440 }, { degree: 1, cents: 50, … }, …] ``` -------------------------------- ### Handle unknown tunings Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/tuning.md Use tryGetTuning to avoid errors when resolving potentially invalid tuning names. ```ts import { getTuning, tryGetTuning } from "musictheoryjs"; getTuning("24-ED"); // throws: unknown tuning "24-ED"; did you mean 24-EDO? tryGetTuning("nope"); // null — the non-throwing form ``` -------------------------------- ### Process semitone and MIDI inputs Source: https://github.com/zachacious/musictheoryjs/blob/master/README.md Shows how to work with semitone patterns, MIDI values, and scale steps while maintaining correct spelling on output. ```ts import { Note, Scale, Chord, intervalFromSemitones, intervalName, scaleStep } from "musictheoryjs"; Note.from("C4").transpose(7).toString(); // "G4" — semitones work directly Note.fromMidi(61).toString(); // "C#4" Chord.fromSemitones("C4", [0, 4, 7]).noteNames(); // ["C4","E4","G4"] Scale.fromSemitones("C4", [0, 2, 4, 5, 7, 9, 11]).noteNames(); intervalName(intervalFromSemitones(7)); // "P5" scaleStep("C4 major", "C4", 2).toString(); // "E4" — up two scale steps Note.from("C#4").midi; // 61 — and back out again ``` -------------------------------- ### Inspect chord quality Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/chords.md Use Chord.from to instantiate a chord and access its properties or boolean quality checks. ```ts const c = Chord.from("Cm"); c.isMajor(); // false c.isMinor(); // true c.isDiminished(); // false c.isAugmented(); // false c.quality; // "min" c.root; // Note C4 c.notes; // Note[] c.toString(); // "Cm" ``` -------------------------------- ### Migrate Instrument and Tuning Operations Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/migration.md Shows how to access note frequency and MIDI values using the new tuning-based system. ```ts import { Note, Scale, TET12, frequencyOfNote } from "musictheoryjs"; const third = Scale.from("C5", "major").degree(3); third.frequency; // => ~659.26 third.midi; // => 76 frequencyOfNote(new Note("A4"), TET12, { frequency: 442 }); // => 442 ``` -------------------------------- ### Generate and transform musical sequences in TypeScript Source: https://github.com/zachacious/musictheoryjs/blob/master/skills/musictheoryjs/SKILL.md Shows how to create melodies, apply swing, calculate timing, arpeggiate chords, and build drum patterns. ```typescript import { Scale } from "musictheoryjs/scale"; import { melody, arpeggiate, swing, sequenceSeconds, drumPattern, GM_DRUMS, mergeStreams, compProgression, bassline } from "musictheoryjs/sequence"; const line = melody(Scale.from("C4", "major").notes, "8"); line.map((e) => e.start); // => [0, 0.5, 1, 1.5, 2, 2.5, 3] swing(line).map((e) => +e.start.toFixed(3)); // => [0, 0.667, 1, 1.667, 2, 2.667, 3] sequenceSeconds(line, 90).map((e) => +e.start.toFixed(3)); // => [0, 0.333, 0.667, 1, 1.333, 1.667, 2] arpeggiate("Cmaj7", { pattern: "updown", duration: "16" }).map((e) => e.pitch.toString()); // => ["C4", "E4", "G4", "B4", "G4", "E4"] const groove = drumPattern({ kick: "x...x...", snare: "..x...x.", hihat: "xxxxxxxx" }, { step: "8" }); groove.filter((e) => e.pitch.midi === GM_DRUMS.kick).map((e) => e.start); // => [0, 2] mergeStreams(compProgression("C major", "ii-V-I"), bassline(["Dm7", "G7", "C"], { style: "roots" })).length; // => 15 ``` -------------------------------- ### Create Notes from Various Inputs Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/notes.md Initialize notes using scientific pitch notation, object parts, or shorthand functions. MIDI numbers and frequencies can also be converted into Note instances. ```ts import { Note, note } from "musictheoryjs"; new Note("C#4"); // from scientific pitch notation new Note({ step: 0, alteration: 1 }); // from parts (octave defaults to 4) note("Eb3"); // `note(...)` is shorthand for `new Note` // From a MIDI number or a frequency (great for MIDI/audio input) Note.fromMidi(60); // C4 Note.fromMidi(61, "flat"); // Db4 Note.fromFrequency(440); // A4 (snaps to nearest 12-TET note) Note.fromFrequency(442); // A4 (a little sharp, still A4) ``` -------------------------------- ### Convert sequences to MIDI and notation Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/sequencing.md Demonstrates converting beat-timed streams to MIDI files and ABC notation, including handling of rests. ```ts import { melody, sequenceToMidi, midiToSequence, sequenceToScore, toABC } from "musictheoryjs"; const line = melody(["C4", "D4", "E4", null, "G4"], "q"); sequenceToMidi(line, { bpm: 140 }).tracks[0].notes[1].start; // 480 — one beat, exactly midiToSequence(sequenceToMidi(line)).length; // 4 — back to beats, no tempo involved toABC(sequenceToScore(line, { key: "C major" })).includes("z"); // true — the rest notated ``` -------------------------------- ### Automate changeset creation Source: https://github.com/zachacious/musictheoryjs/blob/master/RELEASING.md Use this command to author a changeset and commit pending work in one step, avoiding interactive prompts. ```bash bun run release:cut patch "Rewrite README for a JS-developer audience" # then: git push → CI opens the Version Packages PR; merge it to publish ``` -------------------------------- ### Sequence and Export MIDI Source: https://github.com/zachacious/musictheoryjs/blob/master/README.md Create a progression and bassline, apply swing, and export to a MIDI file. ```ts import { compProgression, bassline, swing, arpeggiate, sequenceToMidi, writeMidi, mergeStreams } from "musictheoryjs"; // A played ii-V-I: voice-led hits with a Charleston-style rhythm. const comp = compProgression("C major", "ii-V-I", { rhythm: [1, 0, 0, 1, 0, 0, 0, 0] }); const bass = bassline(["Dm7", "G7", "Cmaj7"]); // walking quarters, chromatic approaches const bytes = writeMidi(sequenceToMidi(mergeStreams(swing(comp), bass), { bpm: 140 })); arpeggiate("Am", { pattern: "updown", octaves: 2 }).length; // => 10 ``` -------------------------------- ### Parse and Suggest Progressions Source: https://github.com/zachacious/musictheoryjs/blob/master/skills/musictheoryjs/SKILL.md Shows how to parse chord progressions into Roman numerals and suggest subsequent chords based on a key. ```ts import { parseProgression, progressionRomans, suggestNextChords } from "musictheoryjs/key"; const steps = parseProgression("C major", "Dm7 | G7 | N.C. | Cmaj7"); steps.map((s) => s.roman?.symbol ?? s.input); // => ["ii7", "V7", "N.C.", "Imaj7"] steps.map((s) => s.function); // => ["SD", "D", "", "T"] progressionRomans("C major", ["C", "A7", "Dm7", "G7"]); // => ["I", "V7/ii", "ii7", "V7"] suggestNextChords("C major", ["Dm7"])[0].chord.toString(); // => "G7" ``` -------------------------------- ### Create and inspect chords Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/chords.md Use Chord.from, Chord.of, or the shorthand chord function to instantiate chords and retrieve their note names. ```ts import { Chord, chord } from "musictheoryjs"; Chord.from("Cmaj7"); // parse a chord symbol (root octave defaults to 4) Chord.of("C4", "min7"); // root note + canonical quality chord("F#m7b5"); // `chord(...)` is shorthand for `Chord.from` Chord.from("Cmaj7").noteNames(); // ["C4", "E4", "G4", "B4"] Chord.from("Bdim7").noteNames(); // ["B4", "D5", "F5", "Ab5"] (Ab, not G#) Chord.of("D4", "min7").noteNames(); // ["D4", "F4", "A4", "C5"] ``` -------------------------------- ### Note Operations and Properties Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/migration.md Demonstrates common note manipulations and property access in v3. ```ts import { Note } from "musictheoryjs"; const note = new Note("E5"); note.pitchClass; // => 4 Note.fromMidi(4 + 12 * 6).toString(); // => "E5" new Note("C4").transpose("A1").toString(); // => "C#4" new Note("D4").transpose("-A1").toString(); // => "Db4" // Bare numbers work too, spelled conventionally: one semitone is a minor // second, so it changes the letter — that's spelling doing its job. new Note("C4").transpose(1).toString(); // => "Db4" new Note("F#4").alteration; // => 1 ``` -------------------------------- ### Initialize and play a scale in TypeScript Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/scales.md Creates a harmonic minor scale from a root note and logs its properties and audio output. ```ts const scale = Scale.from("A3", "harmonicMinor"); log(scale.noteNames()); log("3rd degree:", scale.degree(3).toString()); play(scale); ``` -------------------------------- ### Calculate frequencies and tunings in TypeScript Source: https://github.com/zachacious/musictheoryjs/blob/master/skills/musictheoryjs/SKILL.md Demonstrates calculating note frequencies, using custom tunings, and working with EDO scales. ```ts import { note, frequencyOfNote, frequencyOfDegree, centsTuning, getTuning, justIntonation } from "musictheoryjs"; note("A4").frequency; // => 440 frequencyOfNote(note("C4")); // => ~261.63 frequencyOfNote(note("E4"), justIntonation()); // => ~330 frequencyOfNote(note("A4"), "12-TET", { frequency: 432 }); // => 432 const rast = centsTuning([0, 204, 355, 498, 702, 906, 1057], { name: "Rast" }); rast.centsForDegree(2); // => 355 getTuning("rast").size; // => 7 frequencyOfDegree("24-EDO", 1, { frequency: 440 }); // => ~452.89 ``` -------------------------------- ### Importing from MusicXML Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/notation.md Parses MusicXML documents into beat-timed event streams, preserving key, tempo, and pitch information. ```ts import { fromMusicXML, toMusicXML } from "musictheoryjs"; const doc = fromMusicXML(toMusicXML(["C4", "D4", "E4"], { key: "C major", tempo: 96 })); doc.key.toString(); // "C major" doc.tempo; // 96 doc.stream.map((e) => e.pitch.toString()); // ["C4", "D4", "E4"] doc.stream.map((e) => e.start); // [0, 1, 2] — quarter-note beats doc.parts.length; // 1 ``` -------------------------------- ### Create a key and read its signature Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/keys.md Access the key signature properties for major and minor keys, where count is positive for sharps and negative for flats. ```ts import { Key } from "musictheoryjs"; Key.major("G").signature; // { count: 1, accidentals: [{ letter: "F", alteration: 1 }] } — one sharp (F#) Key.major("F").signature.count; // -1 (one flat) Key.major("C#").signature.count; // 7 (seven sharps) Key.minor("A").signature.count; // 0 ``` -------------------------------- ### Perform note and interval operations Source: https://github.com/zachacious/musictheoryjs/blob/master/README.md Demonstrates note comparison, enharmonic checking, transposition, and scale generation using explicit note objects. ```ts import { Note, Scale, interval, intervalBetween, intervalName } from "musictheoryjs"; new Note("E#4").equals("F4"); // false — different notes new Note("E#4").isEnharmonic("F4"); // true — same pitch new Note("C4").transpose(interval(4, "d")).toString(); // "Fb4" — a diminished fourth, spelled right Scale.from("Cb4", "major").noteNames(); // ["Cb4","Db4","Eb4","Fb4","Gb4","Ab4","Bb4"] // Intervals invert transposition exactly, and a test holds it there. intervalName(intervalBetween(new Note("C4"), new Note("F#4"))); // "A4" ``` -------------------------------- ### Define custom tunings Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/tuning.md Create tunings from cents or ratios and generate scales from them. ```ts import { centsTuning, ratioTuning, scaleFromTuning } from "musictheoryjs"; // A maqam Rast, as a cents table, anchored so its tonic sounds at 264 Hz const rast = centsTuning([0, 204, 355, 498, 702, 906, 1057], { name: "Rast" }); scaleFromTuning(rast, { frequency: 264 }, true); // include the closing octave // A 5-limit major scale from ratios ratioTuning(["1/1", "9/8", "5/4", "4/3", "3/2", "5/3", "15/8"]); ``` -------------------------------- ### Analyze Keys and Roman Numerals Source: https://github.com/zachacious/musictheoryjs/blob/master/skills/musictheoryjs/SKILL.md Demonstrates basic key operations, diatonic chord generation, and Roman numeral conversion. ```ts import { Key, diatonicChords, chordToRoman, romanToChord } from "musictheoryjs/key"; Key.major("C").progression("ii7 V7 Imaj7").map(String); // => ["Dm7", "G7", "Cmaj7"] diatonicChords("C major", { seventh: true }).map(String); // => ["Cmaj7", "Dm7", "Em7", "Fmaj7", "G7", "Am7", "Bm7b5"] chordToRoman("A7", "C major").symbol; // => "V7/ii" romanToChord("V65", "C major").noteNames(); // => ["B4", "D5", "F5", "G5"] romanToChord("VII", "A minor").toString(); // => "G" Key.minor("A").chord(7, { variant: "harmonic" }).toString(); // => "G#dim" ``` -------------------------------- ### Perform manual release Source: https://github.com/zachacious/musictheoryjs/blob/master/RELEASING.md Use these commands as a fallback if the automated CI process is unavailable or requires manual intervention. ```bash bun run version # apply changesets: bump package.json + CHANGELOG npm login # authenticate locally bun run release # build + verify + changeset publish (add --provenance manually if desired) ``` -------------------------------- ### Access Tuning Presets Source: https://github.com/zachacious/musictheoryjs/blob/master/README.md Retrieve information about built-in maqam and raga tuning presets. ```ts import { maqamTuning, ragaTuning, slendro, MAQAM_NAMES, RAGA_NAMES } from "musictheoryjs"; MAQAM_NAMES.length; // 7 RAGA_NAMES.length; // 10 Math.round(ragaTuning("bhairav").centsForDegree(2)); // 386 — a pure major third Math.round(slendro().centsForDegree(1)); // 231 — not any 12-TET step ``` -------------------------------- ### Build a scale with musictheoryjs Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/scales.md Create a Scale instance from a tonic and scale type to retrieve spelled note names. ```ts import { Scale } from "musictheoryjs"; Scale.from("C4", "major").noteNames(); // ["C4", "D4", "E4", "F4", "G4", "A4", "B4"] Scale.from("D4", "dorian").noteNames(); // ["D4", "E4", "F4", "G4", "A4", "B4", "C5"] Scale.from("Bb3", "major").noteNames(); // ["Bb3", "C4", "D4", "Eb4", "F4", "G4", "A4"] — keeps flats ``` -------------------------------- ### Perform note transposition and interval analysis Source: https://github.com/zachacious/musictheoryjs/blob/master/skills/musictheoryjs/SKILL.md Demonstrates creating notes, transposing them using intervals or semitones, and calculating intervals between notes. ```ts import { Note, note, interval, intervalName, transposeNotes } from "musictheoryjs"; note("C4").transpose("P5").toString(); // => "G4" note("C4").transpose(3).toString(); // => "Eb4" note("C4").transpose(interval(4, "d")).toString(); // => "Fb4" Note.fromMidi(61).toString(); // => "C#4" Note.fromMidi(61, "flat").toString(); // => "Db4" note("Eb3").midi; // => 51 intervalName(note("C4").intervalTo("F#4")); // => "A4" transposeNotes(["C4", "E4", "G4"], "M2").map(String); // => ["D4", "F#4", "A4"] ``` -------------------------------- ### Detect Key and Play Melody Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/analysis.md Demonstrates key detection from a set of notes and playback of a defined melody sequence. ```ts const melody = [ { pitch: "C4", start: 0, duration: 0.4 }, { pitch: "E4", start: 0.4, duration: 0.4 }, { pitch: "G4", start: 0.8, duration: 0.6 }, ]; log("key:", detectKey(["C4", "E4", "G4"])[0].key.toString()); play(melody); ``` -------------------------------- ### Exporting musical data to ABC and MusicXML Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/notation.md Demonstrates using toABC and toMusicXML with scales, chords, and custom event arrays to generate notation. ```ts import { toABC, toMusicXML, Scale, Chord } from "musictheoryjs"; toABC(Scale.from("D4", "dorian")); // a run of the scale's notes toMusicXML(Chord.from("Cmaj7")); // one whole-note chord toABC(["C4", "E4", "G4"]); // a melody of quarter notes // Full control: events with durations, chords, and rests toABC( [ { notes: ["C4"], duration: "q." }, { notes: ["D4"], duration: "8" }, { chord: "G7", duration: "h" }, { duration: "q" }, // no notes = a rest ], { key: "C major", timeSignature: "4/4", tempo: 96, title: "Cadence" } ); ``` -------------------------------- ### Generate a basic Euclidean rhythm Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/patterns.md Creates an onset grid by distributing pulses across a fixed number of steps. ```ts import { euclideanRhythm } from "musictheoryjs"; euclideanRhythm(8, 3); // [1, 0, 0, 1, 0, 0, 1, 0] ``` -------------------------------- ### Detection and Analysis Source: https://github.com/zachacious/musictheoryjs/blob/master/skills/musictheoryjs/SKILL.md Functions for key detection, set-theoretic analysis, and counterpoint checking. ```APIDOC ## detectKey(notes) ### Description Performs Krumhansl–Schmuckler key detection on a set of notes. ## forteName(pcset) ### Description Returns the Forte name for a given pitch-class set. ## checkCounterpoint(melody1, melody2) ### Description Analyzes two melodies for counterpoint errors like parallel fifths. ## analyzeHarmony(stream) ### Description Returns a chord timeline with Roman numerals in the detected key. ``` -------------------------------- ### Analyze keys and harmonic structures Source: https://github.com/zachacious/musictheoryjs/blob/master/skills/musictheoryjs/SKILL.md Perform key detection, identify Forte set names, and validate counterpoint between melodic lines. ```ts import { detectKey, forteName, pcsetMask, checkCounterpoint } from "musictheoryjs/analysis"; import { melody } from "musictheoryjs/sequence"; detectKey(["C4", "E4", "G4"])[0].key.toString(); // => "C major" forteName(pcsetMask([0, 4, 7])); // => "3-11" checkCounterpoint(melody(["C5", "D5"], "q"), melody(["F4", "G4"], "q"))[0]?.type; // => "parallel-fifths" ``` -------------------------------- ### Compare interval structures Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/intervals.md Observe how the library distinguishes between enharmonically equivalent intervals by their step and semitone counts. ```ts interval(4, "A"); // { steps: 3, semitones: 6 } interval(5, "d"); // { steps: 4, semitones: 6 } ``` -------------------------------- ### Sequencing and Composition Source: https://github.com/zachacious/musictheoryjs/blob/master/skills/musictheoryjs/SKILL.md Functions for generating musical streams, arpeggios, drum patterns, and applying transformations like swing or transposition. ```APIDOC ## Sequencing Utilities ### melody(notes: Array, duration: string) Creates a melody stream from an array of notes and a duration. ### arpeggiate(chord: string, options: Object) Generates an arpeggio stream for a given chord string. ### drumPattern(pattern: Object, options: Object) Creates a drum sequence based on a pattern object mapping instrument names to rhythm strings. ### swing(stream: Array) Applies a swing transformation to a beat-timed stream. ### mergeStreams(...streams: Array) Combines multiple musical streams into a single stream. ``` -------------------------------- ### Calculate Chroma and Detect Key Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/audio.md Extracts a 12-bin pitch-class profile from audio samples and uses it for key detection. ```ts import { chromagram, detectKey } from "musictheoryjs"; const chroma = chromagram(samples, 44100); // Float64Array(12), normalised chroma.indexOf(Math.max(...chroma)); // dominant pitch class (0 = C) // Use it as weights for key detection detectKey([...chroma]); ``` -------------------------------- ### Generate arpeggios and strums Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/sequencing.md Creates arpeggios or strums from chord symbols or pitch lists. Strums simulate string-based instruments with spread timing. ```ts import { arpeggiate, strum } from "musictheoryjs"; arpeggiate("Am").map((e) => e.pitch.toString()); // ["A4", "C5", "E5"] arpeggiate("Am", { pattern: "updown", octaves: 2 }).length; // 10 arpeggiate("C", { pattern: [0, 2, 1, 2], duration: "16" }).length; // 4 // A downstroke reaches the low string first; all voices ring to the end. strum("G", { spread: 0.04 }).map((e) => e.pitch.toString()); // ["G4", "B4", "D5"] ``` -------------------------------- ### Utilize advanced progression toolkit Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/keys.md Parse complex progressions, identify Roman numerals from chords, and suggest subsequent chords based on functional movement. ```ts import { parseProgression, progressionChords, progressionRomans, suggestNextChords, COMMON_PROGRESSIONS, } from "musictheoryjs"; const steps = parseProgression("C major", "Dm7 | G7 | N.C. | Cmaj7"); steps.map((s) => s.roman?.symbol ?? "-"); // ["ii7", "V7", "-", "Imaj7"] steps.map((s) => s.function); // ["SD", "D", "", "T"] progressionChords("Bb major", "ii-V-I"); // ["Cm7", "F7", "Bbmaj7"] progressionChords("A minor", COMMON_PROGRESSIONS.andalusian ?? []); // ["Am", "G", "F", "E"] progressionRomans("C major", ["C", "A7", "Dm7", "G7"]); // ["I", "V7/ii", "ii7", "V7"] — applied dominants detected suggestNextChords("C major", ["Dm7"])[0]?.chord.toString(); // "G7" ``` -------------------------------- ### Map patterns to time with durationTicks Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/patterns.md Converts abstract rhythm steps into concrete temporal units like MIDI ticks for playback. ```ts import { euclideanRhythm, rhythmToOnsets, durationTicks } from "musictheoryjs"; // One step = a sixteenth note. const step = durationTicks("16"); // 120 ticks at the default 480 PPQ const hits = rhythmToOnsets(euclideanRhythm(16, 5)).map((i) => i * step); // [0, 480, 840, 1200, 1560] ``` -------------------------------- ### Analyze Keys and Progressions Source: https://github.com/zachacious/musictheoryjs/blob/master/README.md Generates chord progressions and analyzes keys or Roman numerals. ```ts import { Key, Chord } from "musictheoryjs"; Key.major("C").progression("ii7 V7 Imaj7").map(String); // ["Dm7","G7","Cmaj7"] Key.major("C").romanNumeral(Chord.from("G7")); // "V7" Key.minor("A").relative().toString(); // "C major" ``` -------------------------------- ### Migrate Chord Operations Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/migration.md Demonstrates the new Chord API for parsing symbols and inverting chords. ```ts import { Chord, invertChord, parseChordSymbol } from "musictheoryjs"; Chord.from({ root: "Ab3", quality: "maj7" }).noteNames(); // => ["Ab3", "C4", "Eb4", "G4"] Chord.from("Abmaj7").noteNames(); // => ["Ab4", "C5", "Eb5", "G5"] parseChordSymbol("Cm7").quality; // => "min7" invertChord("C").noteNames(); // => ["E4", "G4", "C5"] ``` -------------------------------- ### Comparing Tunings and Calculating Deviations Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/tuning.md Provides methods to analyze tuning differences and temperament deviations against pure ratios. ```ts import { justDeviations, compareTunings, pythagorean, justIntonation } from "musictheoryjs"; justDeviations()[4].difference; // 13.69 — 12-TET's major third runs sharp justDeviations()[7].difference; // -1.96 — its fifth is barely flat compareTunings(pythagorean(), justIntonation())[4].difference; // 21.51, the syntonic comma ``` -------------------------------- ### Build intervals with musictheoryjs Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/intervals.md Construct intervals using diatonic step count and quality. The optional third argument allows for stacking augmentations or diminutions. ```ts import { interval } from "musictheoryjs"; interval(5, "P"); // perfect fifth interval(3, "M"); // major third interval(3, "m"); // minor third interval(4, "A"); // augmented fourth interval(5, "d"); // diminished fifth interval(9, "M"); // compound: major ninth interval(5, "A", 2); // doubly augmented fifth ``` -------------------------------- ### Play and log maqam tuning data Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/tuning.md Calculates scale cents and plays a maqam scale using the maqamTuning and scaleFromTuning functions. ```ts const rast = maqamTuning("rast"); log("degree cents:", scaleFromTuning(rast).map((d) => d.cents)); log("12-TET third vs just:", justDeviations()[4].difference.toFixed(2), "cents"); play(scaleFromTuning(rast, { frequency: 264 }, true)); ``` -------------------------------- ### detectNote(samples, sampleRate) Source: https://github.com/zachacious/musictheoryjs/blob/master/skills/musictheoryjs/SKILL.md Analyzes audio samples to detect the musical note corresponding to the detected pitch. ```APIDOC ### detectNote(samples, sampleRate) ### Description Analyzes a mono audio buffer and returns the closest musical note representation. ### Parameters - **samples** (Float32Array|Float64Array) - Required - Mono audio samples. - **sampleRate** (number) - Required - The sample rate of the audio data. ``` -------------------------------- ### Rhythm and Meter Utilities Source: https://github.com/zachacious/musictheoryjs/blob/master/skills/musictheoryjs/SKILL.md Functions for parsing duration strings, calculating beat groupings, and generating rhythmic patterns like Euclidean rhythms. ```APIDOC ## Rhythm Utilities ### parseDuration(duration: string) Parses a duration string (e.g., "8t", "4.") into a duration object. ### beatGrouping(timeSignature: string) Returns an array of beat groupings for a given time signature (e.g., "7/8" -> [3, 2, 2]). ### euclideanRhythm(total: number, pulses: number) Generates a rhythmic pattern as an array of 0s and 1s based on Euclidean distribution. ### tickToPosition(ticks: number, timeSignature: string) Converts absolute ticks to a musical position object (bar, beat, offset). ``` -------------------------------- ### Access built-in scale templates Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/scales.md Interact with the library's scale dictionary to list available templates, verify names, and parse aliases. ```ts import { SCALE_TEMPLATES, SCALE_DEFINITIONS, isScaleName, Scale } from "musictheoryjs"; Object.keys(SCALE_TEMPLATES); // every name and alias SCALE_DEFINITIONS.length; // 92 (one entry per scale) isScaleName("dorian"); // true Scale.from("C4 melodic minor"); // spaced aliases parse too ``` -------------------------------- ### Manipulate Notes and Intervals Source: https://github.com/zachacious/musictheoryjs/blob/master/README.md Demonstrates note comparison, enharmonic checking, and interval transposition. ```ts import { Note, interval } from "musictheoryjs"; new Note("E#4").equals("F4"); // false — different notes new Note("E#4").isEnharmonic("F4"); // true — same pitch new Note("C4").transpose(interval(4, "d")).toString(); // "Fb4" (a diminished fourth, spelled right) ``` -------------------------------- ### Resolve tunings by name Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/tuning.md Access built-in tunings by string name and verify registry contents. ```ts import { frequencyOfNote, parseNote, getTuning, tuningNames } from "musictheoryjs"; frequencyOfNote(parseNote("C4"), "Just"); // 264 — a pure C frequencyOfNote(parseNote("C4"), "Pythagorean"); // 260.74 frequencyOfNote(parseNote("C4")); // 261.63 — 12-TET default getTuning("24-EDO").size; // 24 tuningNames().length; // 34 built in ``` -------------------------------- ### Walk sets by step or degree Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/analysis.md Navigate through set members as a scale, supporting both zero-based steps and one-based degrees. ```ts import { pcsetMask, pcsetStep, pcsetDegree } from "musictheoryjs"; const triad = pcsetMask([0, 4, 7]); pcsetStep(triad, 60, 1); // 64 — one step up from C4 is E4 pcsetStep(triad, 60, 3); // 72 — a full turn is exactly an octave pcsetStep(triad, 60, -1); // 55 — negative steps descend pcsetDegree(triad, 60, 4); // 72 — the same note, numbered from 1 ``` -------------------------------- ### Instantiate and Transpose Notes in TypeScript Source: https://github.com/zachacious/musictheoryjs/blob/master/docs/src/content/docs/guides/notes.md Use the Note class to define a pitch and perform musical transpositions. The play function requires a browser environment with audio support. ```ts const note = new Note("Eb4"); log(note.toString(), "· midi", note.midi, "·", note.frequency.toFixed(2), "Hz"); log("up a fifth:", note.transpose("P5").toString()); play([note, note.transpose("M3"), note.transpose("P5")]); ```