
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
@tonaljs/note
Advanced tools
A collection of functions to manipulate musical notes
ES6:
import { Note } from "tonal";
nodejs:
const { Note } = require("tonal");
single module:
import { get } from "@tonaljs/note";
Note.get(noteName: string) => NoteGiven a note name, it returns an object with the following properties:
Note.get("C4"); // => { name: "C4", midi: 60, ... }
It has several shorthands to retrieve properties easily:
Note.name("fx4"); // => "F##4"
Note.pitchClass("Ab5"); // => "Ab"
Note.accidentals("Eb"); // => 'b'
Note.octave("C4"); // => 4
Note.midi("A4"); // => 69
Note.freq("A4"); // => 440
Note.chroma("D"); // => 2
["C", "D", "E"].map(Note.chroma); // => [0, 2, 4]
Note.fromMidi(midi: number) => stringGiven a midi number, returns the note name. This function is the same as midiToNoteName from @tonaljs/midi
Note.fromMidi(61); // => "Db4"
Note.fromMidi(61.7); // => "D4"
[60, 61, 62].map(Note.fromMidi); // => ["C4", "Db4", "D4"]
There's also a Note.fromMidiSharps version:
Note.fromMidiSharps(61); // => "C#4"
Note.fromFreq(freq: number) => stringGiven a frequency in Hz, returns the note name.
Note.fromFreq(440); // => "A4"
It rounds to the nearest name:
[440, 550, 660].map(t.Note.fromFreq); // => [ 'A4', 'Db5', 'E5' ]
There's also a Note.fromFreqSharps version:
[440, 550, 660].map(t.Note.fromFreqSharps); // => [ 'A4', 'C#5', 'E5' ]
transpose(note: string, interval: string) => stringTranspose a note by an interval. It returns the note name or "" if not valid parameters.
Examples:
Note.transpose("d3", "3M"); // => "F#3"
Note.transpose("D", "3M"); // => "F#"
transposeBy and transposeFrom are curried versions of this function to make easy work with arrays:
["C", "D", "E"].map(Note.transposeBy("5P"));
// => ["G", "A", "B"]
["1P", "3M", "5P"].map(Note.transposeFrom("C"));
// => ["C", "E", "G"]
transposeFifths(noteName: string, fifths: number) => stringTranspose a note a given number of fifths:
Note.transposeFifths("G4", 3); // => "E6"
Note.transposeFifths("G", 3); // => "E"
[0, 1, 2, 3, 4, 5, 6].map((n) => transposeFifths("F#", n));
// => ["F#", "C#", "G#", "D#", "A#", "E#", "B#"]
[0, -1, -2, -3, -4, -5, -6].map((n) => transposeFifths("Bb", n));
// => ["Bb", "Eb", "Ab", "Db", "Gb", "Cb", "Fb"]
Note.distance(from: string, to: string) => stringFind the interval between two notes:
Note.distance("C", "D").toEqual("2M");
Note.distance("C3", "E3").toEqual("3M");
Note.distance("C3", "E4").toEqual("10M");
names(array?: any[]) => string[]Get note names of an array of anything. Notice that names are normalized:
Note.names(["fx", "bb", 12, "nothing", {}, null]); // => ["F##", "Bb"];
Without parameters, it returns a list of natural pitch classes:
Note.names(); // => ["C", "D", "E", "F", "G", "A", "B"]
You may be in a situation where you have note names with octaves, but don't want them, remove them like this:
Note.names(["C2", "C#3", "Db4", 12, "nothing", {}, null]).map(Note.pitchClass); // => ['C', 'C#', 'Db']
sortedNames(array?: any[], comparator?: NoteComparator) => string[]Sort an array of note names in ascending order. Pitch classes are listed before notes. Anything that is not a note is removed:
Note.sortedNames(["c2", "c5", "c1", "c0", "c6", "c"]);
// => ['C', 'C0', 'C1', 'C2', 'C5', 'C6']
Note.sortedNames(["c", "F", "G", "a", "b", "h", "J"]);
// => ['C', 'F', 'G', 'A', 'B']
An optional comparator can be passed as a second argument:
Note.sortedNames(["c2", "c5", "c1", "c0", "c6", "c"], Note.descending);
// => ['C6', 'C5', 'C2', 'C3', 'C1', 'C0']
sortedUniqNames(array?: any[]) => string[]Sort notes ascending and remove duplicates.
simplify(noteName: string) => stringGiven a note name, return the same note with less accidentals (or "" if not a valid note):
Note.simplify("C#"); // => "C#"
Note.simplify("C##"); // => "D"
Note.simplify("C###"); // => "D#"
enharmonic(noteName: string, pitchClass?: string) => stringGiven a note name, returns its enharmonic (or "" if not valid note):
Note.enharmonic("C#"); // => "Db"
Note.enharmonic("C##"); // => "D"
Note.enharmonic("C###"); // => "Eb"
Note.enharmonic("C##b"); // => ""
Using enharmonic on a natural will return the same value passed in:
Note.enharmonic("C"); // => "C"
Note.enharmonic("C4"); // => "C4"
The destination pitch class can be enforced to calculate the octave:
Note.enharmonic("F2", "E#"); // => "E#2"
Note.enharmonic("B2", "Cb"); // => "Cb3"
Note.enharmonic("C2", "B#"); // => "B#1"
Enforced pitch class must have the same chroma as the note, otherwise "" is returned:
Note.enharmonic("F2", "Eb"); // => ""
FAQs
Parse and manipulate music notes in scientific notation
The npm package @tonaljs/note receives a total of 8,360 weekly downloads. As such, @tonaljs/note popularity was classified as popular.
We found that @tonaljs/note demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.