npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

midi-vibe

v0.0.20

Published

Typed music theory, tuning, MIDI control, and rhythm primitives for TypeScript.

Readme

midi-vibe

Typed music theory, tuning, MIDI control, and rhythm primitives for TypeScript.

Install

bun add midi-vibe

Usage

import {
  INTERVAL,
  MidiReferenceNote,
  createMidiNote,
  midiNoteToFrequency,
  frequencyHertz,
  transpose,
} from "midi-vibe";

const middleC = createMidiNote(MidiReferenceNote.C4);
const eFlat = transpose(middleC, INTERVAL.MinorThird);
const frequency = midiNoteToFrequency(eFlat);

console.log(frequencyHertz(frequency));

Generate the example MIDI projects from the repository:

bun run examples

Build your own Standard MIDI File Type 1 composition:

import {
  GeneralMidiProgram,
  MidiFileChannel,
  MidiFileController,
  MidiFileEnvelopeCurve,
  MidiFileFormSectionName,
  MidiFileKeyMode,
  MidiFilePitchClass,
  MidiFileVelocity,
  createMidiCatalogBuilder,
  createMidiCompositionBuilder,
  serializeMidiComposition,
} from "midi-vibe";

const composition = createMidiCompositionBuilder({
  slug: "first-piece",
  title: "First Piece",
  description: "A two-bar chord sketch.",
  tempoBpm: 96,
  timeSignature: { numerator: 4, denominator: 4 },
  keySignature: { fifths: 0, mode: MidiFileKeyMode.Major },
  length: { bars: 2 },
})
  .addFormSection({
    name: MidiFileFormSectionName.Intro,
    startBar: 0,
    barCount: 2,
    description: "Opening phrase.",
  })
  .addTrack({
    name: "Piano",
    channel: MidiFileChannel.Piano,
    program: GeneralMidiProgram.AcousticGrandPiano,
  }, (track) => {
    track
      .addPattern({
        repeat: 2,
        every: { beats: 2 },
        events: [{
          kind: "chord",
          at: { bar: 0, beat: 0 },
          duration: { beats: 1.5 },
          notes: [
            { pitchClass: MidiFilePitchClass.C, octave: 4 },
            { pitchClass: MidiFilePitchClass.E, octave: 4 },
            { pitchClass: MidiFilePitchClass.G, octave: 4 },
          ],
          velocity: MidiFileVelocity.Medium,
        }],
      })
      .addEnvelope({
        controller: MidiFileController.Expression,
        sampleStep: { beats: 1 },
        points: [
          { at: { bar: 0 }, value: 72, curve: MidiFileEnvelopeCurve.Step },
          { at: { bar: 1 }, value: 96 },
          { at: { bar: 2 }, value: 64 },
        ],
      });
  })
  .build();

const midiBytes = serializeMidiComposition(composition);
const catalog = createMidiCatalogBuilder()
  .addComposition(composition)
  .build();

API Areas

  • Branded scalar primitives for frequencies, cent offsets, MIDI notes, controllers, PPQN values, ticks, intervals, and pitch classes.
  • Equal temperament and just intonation helpers.
  • Harmonic, melodic, rhythmic, tuplet, and polyrhythm context builders.
  • MIDI control-change envelopes with deterministic step and linear sampling.
  • Standard MIDI File Type 1 composition serialization, builder-based catalog generation, track metadata, General MIDI program/drum helpers, and pitch bend events.
  • Pitch transforms, MIDI note/frequency conversion, inversion, transposition, and quantization.

For maintainers and agent workflows, see the public API surface map in docs/public-api-map.md before adding or moving root exports.

Project Structure

Source is organized into domain-driven layers. The public package API is unchanged; root modules re-export the new layout.

| Layer | Path | Responsibility | | --- | --- | --- | | Domain | src/domain/** | Branded scalars and pure theory models (pitch, harmony, tuning, rhythm, melody, MIDI control) | | Application | src/application/** | Composition use-case orchestration (form, rhythm, motifs, analysis) | | Infrastructure | src/infrastructure/** | SMF serialization, parsing, validation, catalog IO, and byte-level MIDI contracts | | Shared | src/shared/** | Cross-cutting utilities such as timing conversion and rounding |

Compatibility entry points at the repository root still map to those layers:

  • src/index.ts — main public API for theory, tuning, rhythm, composition helpers, and MIDI utilities
  • src/midi-projects.ts — Standard MIDI File builders, serializers, General MIDI constants, and catalog helpers
  • src/composition-*.ts, src/time.ts — targeted re-exports for development and tests

Example MIDI generators live under examples/<project>/generate.ts. Generated .mid and catalog.json files are example artifacts, not source modules. Tests live in test/*.test.ts and import through the midi-vibe path alias.

Theory Naming Policy

  • Octaves follow the common MIDI convention where C4 is MIDI note 60 and A4 is MIDI note 69. MIDI rendering accepts octave-specific pitches only when they resolve to note numbers 0..127.
  • Plan-level pitch names use ASCII spellings: letters A through G, accidentals #, b, ##, and bb. Unicode accidentals are not part of the public naming convention.
  • Enharmonic spelling is preserved in harmonic plans. For example, C# and Db share the same chromatic ordinal but keep distinct names until an explicit MIDI rendering boundary such as harmonicPitchToMidiPitch.
  • Minor modes are explicit: natural-minor, harmonic-minor, and melodic-minor are separate plan values. MIDI key-signature meta events can only encode major or minor, so minor variants collapse to MIDI minor only at export boundaries chosen by the caller.
  • Modal scale constants include ionian/aeolian aliases, the diatonic modes, melodic-minor derived modes such as lydian-dominant and altered, and harmonic-minor derived modes such as phrygian-dominant.
  • Chord labels are caller-authored lead-sheet or analysis labels stored alongside structured root, quality, optional bass, chord tones, and voicing. Roman numerals such as V/V are labels, not inferred pitch content.
  • MIDI key signatures use SMF fifths -7..7 plus mode major or minor. Modal tonal centers and enharmonic spelling that MIDI cannot represent remain plan metadata.
  • Export intent is explicit: exact-intent preserves spelling, Roman numerals, modal context, just-intonation ratios, cent offsets, and controller intent without claiming MIDI realization; midi-realized-approximation records nearest MIDI note, residual cents, pitch-bend range assumptions, channel allocation, and validation messages; metadata-only-warning keeps unsupported meaning as metadata with warnings.
  • MIDI 1.0 pitch bend is channel state, not per-note tuning. Portable microtonal output requires a known receiver bend range and careful channel allocation; otherwise midi-vibe reports the approximation or preserves the tuning intent as metadata. Future export bridges can carry this same intent model into richer formats such as MusicXML, MIDI Tuning Standard, MIDI 2.0, or DAW package metadata.
  • Composition-plan microtonal lanes render to MIDI only when exportMode or mode is midi-realized-approximation. The renderer emits pitch bend before the nearest MIDI note and centers bend after note-off on the part channel; independent simultaneous bends should be split into separate parts/channels. Set pitchBendRangeCents when the receiver is configured, or midi-vibe records the default 200-cent assumption and a validation warning in metadata.tuningAssumptions.microtonalRealizations.

Strategic Follow-Ons

These differentiators are intentionally documented as post-foundation explorations, not immediate sprint tickets. They should be picked up only after the public API map, composition-domain extraction, structured validation reports, readback fixtures, and example artifact metadata contract are stable enough to make their behavior reviewable.

| Exploration | Foundation dependencies | Notes before pickup | | --- | --- | --- | | Composition diffing | Requires API ownership to identify public comparison surfaces, domain extraction to compare plan primitives before MIDI bytes, validation reports to classify structural mismatches, readback fixtures to prove rendered differences, and artifact metadata to record source seeds, recipes, package versions, and transform chains. | Inputs must be deterministic and outputs must be reviewable as structured summaries, not only byte-level diffs. | | Hidden harmony explorer | Requires API ownership for theory and composition model placement, domain extraction for cycle relationships and Roman-numeral/chord models, validation reports for unsupported or ambiguous analysis, readback coverage when explorations render to MIDI, and metadata for provenance of generated studies. | Cycle-harmony concepts should remain explicit analysis and composition models: cycle type, tonic slot, offset, chord quality, alteration, and resolution intent. Do not encode them as opaque preset magic. | | Constraint-solved arrangement sketches | Requires API ownership for solver-facing builders, domain extraction for forms, rhythms, motifs, harmony, parts, and arrangement constraints, validation reports for unsatisfied constraints, readback fixtures for rendered sketches, and metadata for solver version, seed, constraints, and selected solution. | Solvers must accept deterministic inputs and return reviewable outputs, including accepted constraints, rejected constraints, and chosen tradeoffs. | | Branded timing conversions | Requires API ownership for timing entry points, domain extraction for musical time and tick/PPQN scalars, validation reports for invalid timing boundaries, readback fixtures for tempo/meter-sensitive conversions, and metadata only when conversions affect generated artifacts. | This can be picked up earlier only if sprint planning identifies active timing defects; otherwise it should stay behind the foundation and trust work. |

Development

Install dependencies:

bun install

Run tests, type checks, and lint:

bun test
bun run typecheck
bun run check

Build the publishable package:

bun run build

Preview the npm package contents:

bun run pack:dry-run

Generate the MIDI examples:

bun run examples