# @tonaljs/voicing

> Voicings and Voice Leading for Chords

Latest version **5.1.3** (published 2026-01-18) · MIT license · 0 weekly downloads

## Install

```sh
npm install @tonaljs/voicing
pnpm add @tonaljs/voicing
yarn add @tonaljs/voicing
bun add @tonaljs/voicing
```

## Health

**Score 55/100 (C)** — status: stable.

Positive: has types; esm support; no vulnerabilities.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 5.1.3 |
| Published | 2026-01-18 |
| First published | 2023-11-28 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 6 |
| Unpacked size | 24.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | felix91@gmail.com |
| Maintainers | danigb |
| Keywords | chord, voicing, voicings, music, theory, @tonaljs |

## Links

- npm: https://www.npmjs.com/package/@tonaljs/voicing
- npm.io page: https://npm.io/package/@tonaljs/voicing

## Dependencies (6)

- [@tonaljs/note](https://npm.io/package/@tonaljs/note.md) 4.12.1
- [@tonaljs/chord](https://npm.io/package/@tonaljs/chord.md) 6.1.2
- [@tonaljs/range](https://npm.io/package/@tonaljs/range.md) 4.9.2
- [@tonaljs/interval](https://npm.io/package/@tonaljs/interval.md) 5.1.0
- [@tonaljs/voice-leading](https://npm.io/package/@tonaljs/voice-leading.md) 5.1.2
- [@tonaljs/voicing-dictionary](https://npm.io/package/@tonaljs/voicing-dictionary.md) 5.1.3

## Recent versions

- 5.1.3 (latest) — 2026-01-18
- 5.1.2 — 2025-06-04
- 5.1.1 — 2025-01-03
- 5.1.0 — 2024-07-23
- 5.0.3 — 2024-02-03
- 5.0.2 — 2024-02-03
- 5.0.1 — 2024-01-04
- 5.0.0 — 2023-11-28

## README

# @tonaljs/voicing

Contains functions to generate voicings. If you're not sure what voicings are, [watch this video](https://www.youtube.com/watch?v=VR3o45Pwx9Y).

## Usage

ES6:

```js
import { Voicing } from "tonal";
```

Nodejs:

```js
const { Voicing } = require("tonal");
```

## API

### Voicing.search

```ts
Voicing.search(chord: string, range?: [string, string], dictionary?: VoicingDictionary): string[][]
```

This method returns all possible voicings of the given chord, inside the given range, as defined in the dictionary:

```ts
Voicing.search("C^7", ["E3", "D5"], { "^7": ["3M 5P 7M 9M", "7M 9M 10M 12P"] });
/* => [
  ['E3', 'G3', 'B3', 'D4'],
  ['E4', 'G4', 'B4', 'D5'],
  ['B3', 'D4', 'E4', 'G4'],
] */
```

The VoicingDictionary param uses the format of [@tonaljs/voicing-dictionary](../voicing-dictionary). Instead of defining your own, you could also use an existing dictionary from there:

```ts
import { VoicingDictionary } from "@tonaljs/voicing-dictionary";
Voicing.search("C^7", ["E3", "D5"], VoicingDictionary.lefthand);
/* => [
  ['E3', 'G3', 'B3', 'D4'],
  ['E4', 'G4', 'B4', 'D5'],
  ['B3', 'D4', 'E4', 'G4'],
] */
```

If no range and/or dictionary is given, there is a fallback to [default values](./index.ts) (look for defaultRange / defaultDictionary):

```ts
Voicing.search("C^7");
/* => [
  ['E3', 'G3', 'B3', 'D4'],
  ['E4', 'G4', 'B4', 'D5'],
  ['B3', 'D4', 'E4', 'G4'],
] */
```

### Voicing.get

```ts
Voicing.get(
  chord: string,
  range?: [string, number],
  dictionary?: VoicingDictionary,
  voiceLeading?: VoiceLeading,
  lastVoicing?: string[]
) => string[];
```

Returns the best voicing for **chord** inside the given **range**, as contained in the **dictionary**, using **voiceLeading** to decide which voicing to pick after **lastVoicing**. Internally calls Voicing.search to generate the available voicings:

```ts
Voicing.get("Dm7");
/* ['F3', 'A3', 'C4', 'E4']); */
Voicing.get("Dm7", ["F3", "A4"], lefthand, topNoteDiff);
/* ['F3', 'A3', 'C4', 'E4']; */
const last = ["C4", "E4", "G4", "B4"];
Voicing.get("Dm7", ["F3", "A4"], lefthand, topNoteDiff, last);
/* ['C4', 'E4', 'F4', 'A4']; */ // => A4 is closest to B4
```

## Optional: Voicing.analyze

```ts
export declare function analyze(voicing: string[]): {
  topNote: string;
  bottomNote: string;
  midiAverage: number;
};
```

Returns some useful info on the given voicing:

```ts
expect(Voicing.analyze(["C4", "E4", "G4", "B4"])).toEqual({
  topNote: "B4",
  bottomNote: "C4",
  midiAverage: 85.4, // did not check :)
  // many more values possible
});
```

## Optional: Voicing.analyzeTransition

```ts
export declare function analyzeTransition(
  from: string[],
  to: string[]
): {
  topNoteDiff: number;
  bottomNoteDiff: number;
  movement: number;
};
```

Returns some useful info on the given voice transition

```ts
expect(
  Voicing.analyzeTransition(["C4", "E4", "G4", "B4"], ["D4", "F4", "A4", "C5"])
).toEqual({
  topNoteDiff: 1,
  bottomNoteDiff: 2,
  movement: 5,
});
```

Could also use intervals instead of semitones (but semitones are easier to compare)

## Optional: Voicing.intervalSets

```ts
export declare function intervalSets(
  chordSymbol: string,
  dictionary: VoicingDictionary
);
```

Get possible interval sets for given chord in given dictionary:

```ts
expect(Voicing.intervalSets("M7", lefthand)).toEqual([
  ["3M 5P 7M 9M", "7M 9M 10M 12P"],
]);
// could also be used with chord symbol (ignore root)
expect(Voicing.intervalSets("CM7", lefthand)).toEqual([
  ["3M 5P 7M 9M", "7M 9M 10M 12P"],
]);
```

Note that it works, even if the chord symbol "M7" is just an alias of the "^7" symbol used in the dictionary.

## Optional: Voicing.searchSets

```ts
export declare function searchSets(
  intervalSets: string[][],
  range: string[],
  root: string
);
```

Renders all sets of notes that represent any of the interval sets inside the given range, relative to the root:

```ts
expect(
  Voicing.searchSets(
    [
      ["1P", "3M", "5P"],
      ["3M", "5P", "8P"],
    ],
    ["C3", "G4"],
    "C"
  )
).toEqual([
  ["C3", "E3", "G3"],
  ["E3", "G3", "C4"],
  ["C4", "E4", "G4"],
]);
```

changes:

- renamed to searchSets (similar to Voicing.search)

---
_Source: https://npm.io/package/@tonaljs/voicing · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
