Symbolic library

Check package availability and use Symbolic's JavaScript and TypeScript functions for notes, chords and rhythm.

Symbolic provides headless music-theory functions for notes, intervals, chords, scales, sets, rhythm and notation conversion. The functions return musical data. Your application supplies playback, MIDI delivery or UI.

Installation and availability

Symbolic is included in the next maruaudio package through focused subpaths. The published maruaudio@0.0.2 does not contain these entries. Use a qualified Symbolic-enabled package tarball until that release is published; the examples below describe that new package API.

After the Symbolic-enabled release is available, install the single package:

bash
npm install maruaudio

To try a prepared package before publication, install its tarball instead:

bash
npm install ./maruaudio-<version>.tgz

There is no separate Symbolic, MIDI or theory package to install for these imports. The package bundles the required implementation and declarations. Save an example as example.mjs and run node example.mjs in your project. JavaScript and TypeScript use the same import paths.

ImportPurpose
maruaudio/symbolicCommon notes, sets, intervals, durations and notation conversions
maruaudio/symbolic/rhythmRhythm patterns, named timelines, metrics and continuation
maruaudio/symbolic/gridHeadless grid layout catalog and interval geometry
maruaudio/symbolic/refsMusical references and notation bridges with explicit context and losses
maruaudio/symbolic/lead-sheetEditable lead sheets and timed harmonic data
maruaudio/symbolic/jazz-practiceSeeded practice phrases and instrument-aware exercises
maruaudio/symbolic/percussionPolyphonic percussion annotations
maruaudio/symbolic/catalogMusical concepts and relationships
maruaudio/symbolic/libraryThe full library, including advanced analysis, song structures and generation

The common entry keeps advanced reference registries and song structures out of its runtime closure. Choose a focused entry for your task, or opt into /library when you need the complete API. These are headless musical-data functions; they do not open MIDI devices, start an audio engine or provide a realtime Processor backend.

Explore the results in the Symbolic catalog. To compose and play patterns inside Code Sequencer, follow Symbolic Cycle, which has its own song language and execution environment.

Notes and MIDI pitches

Parse a note name and convert a MIDI pitch to a frequency. MIDI pitch 69 is A4; frequencies are in hertz.

ts
import { noteFromMidi, parseNote } from "maruaudio/symbolic"

const middleC = parseNote("C4")
const a4 = noteFromMidi(69)

console.log(middleC.midi) // 60
console.log(a4.freq) // 440

Analyze a MIDI file

In Node.js, pass the bytes of a Standard MIDI File to midiHarmony from the full library. It returns note counts, a pitch-class histogram and an estimated key. Histogram entries run from C through B and weight notes by duration in MIDI ticks; counts records note counts for those same pitch classes.

ts
import { readFileSync } from "node:fs"
import { midiHarmony } from "maruaudio/symbolic/library"

const analysis = midiHarmony(readFileSync("example.mid"))

console.log(analysis.notes)
console.log(analysis.histogram)
console.log(analysis.counts)

In a browser, pass a Uint8Array made from the selected file's ArrayBuffer. File selection and MIDI device access remain responsibilities of your app.

Transpose a chord

A note set retains octaves. Transposition takes a number of semitones; moving C major up seven semitones gives G major in the corresponding register.

ts
import { parseNoteSet, transposeNoteSet } from "maruaudio/symbolic"

const cMajor = parseNoteSet("60-64-67")
const gMajor = transposeNoteSet(cMajor, 7)

console.log(gMajor.notes.map(note => note.midi)) // [67, 71, 74]

For octave-independent membership, use a pitch-class set instead. The pitch-class set catalog explores that distinction.

Convert rhythm notation

Convert explicit event positions to a grid, then to successive durations. Positions and durations use quarter-note beats. The 4| prefix means four cells per beat; x attacks, = continues a note and . rests.

ts
import { convertRhythmNotation } from "maruaudio/symbolic"

const grid = convertRhythmNotation("0:0.25,r0.25:0.75,1:1", "positions", "grid")
console.log(grid) // "4|x...x==="
console.log(convertRhythmNotation(grid, "grid", "beats")) // "0.25,r0.75,1"

Parse an onset pattern

The rhythm entry parses an eight-step binary pattern without supplying a clock or playback host:

ts
import { parseRhythmSpec } from "maruaudio/symbolic/rhythm"

const { pattern } = parseRhythmSpec("10010010", "binary")
console.log(pattern.steps) // 8
console.log(pattern.onsets) // [0, 3, 6]

Browse Symbolic for concepts and notation examples, or follow Symbolic Cycle to turn musical values into patterns inside Code Sequencer.