@tonaljs/voicing
Version:
Voicings and Voice Leading for Chords
188 lines (148 loc) • 4.2 kB
Markdown
# /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 [/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)