tonal-guitar 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,602 @@
1
+ # tonal-guitar [![npm version](https://img.shields.io/npm/v/tonal-guitar.svg?style=flat-square)](https://www.npmjs.com/package/tonal-guitar)
2
+
3
+ > Guitar fretboard, shapes, patterns, and sequences — built on Tonal.js
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install tonal-guitar @tonaljs/note @tonaljs/interval
9
+ ```
10
+
11
+ Optional peer dependencies for scale/chord/key integration:
12
+
13
+ ```bash
14
+ npm install @tonaljs/scale @tonaljs/chord @tonaljs/key
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ```js
20
+ import {
21
+ buildFrettedScale,
22
+ get,
23
+ walkPattern,
24
+ thirds,
25
+ toAsciiTab,
26
+ toAlphaTeX,
27
+ } from "tonal-guitar";
28
+ ```
29
+
30
+ ## Quick Start
31
+
32
+ ```js
33
+ import {
34
+ buildFrettedScale,
35
+ get,
36
+ walkPattern,
37
+ thirds,
38
+ toAsciiTab,
39
+ toAlphaTeX,
40
+ } from "tonal-guitar";
41
+
42
+ // 1. Get a shape and build a scale on the fretboard
43
+ const shape = get("CAGED E Shape");
44
+ const scale = buildFrettedScale(shape, "A");
45
+
46
+ // 2. Generate a pattern and walk it
47
+ const pattern = thirds(7); // ascending thirds over 7-note scale
48
+ const notes = walkPattern(scale, pattern);
49
+
50
+ // 3. Output as ASCII tab or AlphaTeX
51
+ console.log(toAsciiTab(notes));
52
+ console.log(toAlphaTeX(notes, { tempo: 100, duration: 8 }));
53
+ ```
54
+
55
+ ## API
56
+
57
+ ### Tuning Constants
58
+
59
+ Pre-defined tunings as `string[]` arrays (low string to high string):
60
+
61
+ ```js
62
+ import { STANDARD, DROP_D, DADGAD, OPEN_G, STANDARD_7, STANDARD_8 } from "tonal-guitar";
63
+
64
+ STANDARD; // => ["E2", "A2", "D3", "G3", "B3", "E4"]
65
+ DROP_D; // => ["D2", "A2", "D3", "G3", "B3", "E4"]
66
+ DADGAD; // => ["D2", "A2", "D3", "G3", "A3", "D4"]
67
+ OPEN_G; // => ["D2", "G2", "D3", "G3", "B3", "D4"]
68
+ STANDARD_7; // => ["B1", "E2", "A2", "D3", "G3", "B3", "E4"]
69
+ STANDARD_8; // => ["F#1", "B1", "E2", "A2", "D3", "G3", "B3", "E4"]
70
+ ```
71
+
72
+ ### Fretboard Math
73
+
74
+ #### `noteAt(tuning: string[], stringIndex: number, fret: number) => string`
75
+
76
+ Get the note name at a string/fret position:
77
+
78
+ ```js
79
+ noteAt(STANDARD, 0, 5); // => "A2" (5th fret, low E string)
80
+ noteAt(STANDARD, 1, 3); // => "C3" (3rd fret, A string)
81
+ ```
82
+
83
+ #### `fretFor(tuning: string[], stringIndex: number, targetNote: string) => number | null`
84
+
85
+ Reverse lookup — find which fret a note is on a given string:
86
+
87
+ ```js
88
+ fretFor(STANDARD, 0, "A2"); // => 5
89
+ fretFor(STANDARD, 1, "C3"); // => 3
90
+ ```
91
+
92
+ #### `findNearestFret(tuning: string[], stringIndex: number, pitchClass: string) => number | null`
93
+
94
+ Find the lowest fret where a pitch class appears on a string:
95
+
96
+ ```js
97
+ findNearestFret(STANDARD, 0, "A"); // => 5
98
+ findNearestFret(STANDARD, 1, "A"); // => 0
99
+ ```
100
+
101
+ #### `findFretInPosition(tuning: string[], stringIndex: number, pitchClass: string, referenceFret: number, span?: number) => number | null`
102
+
103
+ Find a pitch class within a position window centered on a reference fret:
104
+
105
+ ```js
106
+ findFretInPosition(STANDARD, 0, "A", 5, 5); // => 5
107
+ ```
108
+
109
+ #### `findNote(pitchClass: string, tuning?: string[], fretRange?: [number, number]) => FretboardPosition[]`
110
+
111
+ Find all positions of a pitch class across the fretboard:
112
+
113
+ ```js
114
+ findNote("A"); // => [{string: 0, fret: 5, note: "A2", midi: 45}, ...]
115
+ findNote("A", STANDARD, [0, 12]); // limit to first 12 frets
116
+ ```
117
+
118
+ #### `fretboard(tuning?: string[], fretRange?: [number, number]) => FretboardPosition[]`
119
+
120
+ Generate the complete fretboard grid:
121
+
122
+ ```js
123
+ fretboard(STANDARD, [0, 4]); // every note on strings 0-5, frets 0-4
124
+ ```
125
+
126
+ ### Shape Registry
127
+
128
+ Built-in shapes are registered at import time: CAGED scale shapes (5), CAGED chord shapes (5), 3NPS patterns (7), and pentatonic boxes (5).
129
+
130
+ #### `get(name: string) => ScaleShape | undefined`
131
+
132
+ Retrieve a scale shape by name:
133
+
134
+ ```js
135
+ get("CAGED E Shape"); // => { name: "CAGED E Shape", system: "caged", strings: [...], ... }
136
+ get("3NPS Pattern 1"); // => { name: "3NPS Pattern 1", system: "3nps", ... }
137
+ ```
138
+
139
+ #### `all() => ScaleShape[]`
140
+
141
+ Get all registered scale shapes.
142
+
143
+ #### `names() => string[]`
144
+
145
+ Get all registered scale shape names:
146
+
147
+ ```js
148
+ names(); // => ["CAGED E Shape", "CAGED D Shape", "CAGED C Shape", ...]
149
+ ```
150
+
151
+ #### `add(shape: ScaleShape) => ScaleShape`
152
+
153
+ Register a custom shape:
154
+
155
+ ```js
156
+ add({
157
+ name: "My Custom Shape",
158
+ system: "custom",
159
+ strings: [["1P", "2M"], ["4P", "5P"], null, null, null, null],
160
+ rootString: 0,
161
+ });
162
+ ```
163
+
164
+ #### `removeAll() => void`
165
+
166
+ Clear all registered shapes.
167
+
168
+ #### `chordShapes`
169
+
170
+ Separate registry for chord shapes with the same API: `chordShapes.get()`, `chordShapes.all()`, `chordShapes.names()`, `chordShapes.add()`, `chordShapes.removeAll()`.
171
+
172
+ ### Build Engine
173
+
174
+ #### `buildFrettedScale(shape: ScaleShape, root: string, tuning?: string[]) => FrettedScale`
175
+
176
+ Apply a scale shape to a root note and tuning, returning all fretted positions:
177
+
178
+ ```js
179
+ const scale = buildFrettedScale(get("CAGED E Shape"), "A");
180
+ // => {
181
+ // empty: false,
182
+ // root: "A",
183
+ // scaleType: "",
184
+ // scaleName: "",
185
+ // shapeName: "CAGED E Shape",
186
+ // tuning: ["E2", "A2", "D3", "G3", "B3", "E4"],
187
+ // notes: [
188
+ // { string: 0, fret: 5, note: "A2", pc: "A", interval: "1P", degree: 1, midi: 45, ... },
189
+ // { string: 0, fret: 7, note: "B2", pc: "B", interval: "2M", degree: 2, midi: 47, ... },
190
+ // ...
191
+ // ]
192
+ // }
193
+ ```
194
+
195
+ Each `FrettedNote` contains:
196
+ - `string` — 0-indexed string (0 = lowest)
197
+ - `fret` — fret number
198
+ - `note` — full note name with octave (e.g. `"A2"`)
199
+ - `pc` — pitch class (e.g. `"A"`)
200
+ - `interval` — interval from root (e.g. `"1P"`, `"3M"`)
201
+ - `scaleIndex` — 0-based position in scale
202
+ - `degree` — 1-based degree (scaleIndex + 1)
203
+ - `intervalNumber` — numeric part of interval (e.g. 3 for `"3M"`)
204
+ - `midi` — MIDI number
205
+
206
+ Returns a `FrettedScale` with `empty: true` for invalid inputs.
207
+
208
+ #### `applyChordShape(shape: ChordShape, root: string, tuning?: string[]) => Fingering`
209
+
210
+ Apply a chord shape to a root, returning a `Fingering` with per-string fret numbers:
211
+
212
+ ```js
213
+ const chord = applyChordShape(chordShapes.get("E Shape"), "A");
214
+ // => {
215
+ // positions: [...FrettedNote[]],
216
+ // frets: [5, 7, 7, 6, 5, 5],
217
+ // root: "A",
218
+ // shapeName: "E Shape",
219
+ // startFret: 5
220
+ // }
221
+ ```
222
+
223
+ ### Pattern Generators
224
+
225
+ All generators return `number[]` degree sequences.
226
+
227
+ #### `ascendingIntervals(scaleLength: number, interval: number, octaves?: number) => number[]`
228
+
229
+ Generate ascending interval pattern:
230
+
231
+ ```js
232
+ ascendingIntervals(7, 2); // 3rds: [1,3, 2,4, 3,5, 4,6, 5,7, 6,8]
233
+ ascendingIntervals(7, 3); // 4ths: [1,4, 2,5, 3,6, 4,7, 5,8]
234
+ ```
235
+
236
+ #### `descendingIntervals(scaleLength: number, interval: number, startDegree?: number) => number[]`
237
+
238
+ Generate descending interval pattern:
239
+
240
+ ```js
241
+ descendingIntervals(7, 2); // 3rds: [8,6, 7,5, 6,4, 5,3, 4,2, 3,1]
242
+ ```
243
+
244
+ #### `ascendingLinear(from: number, to: number) => number[]`
245
+
246
+ ```js
247
+ ascendingLinear(1, 8); // => [1, 2, 3, 4, 5, 6, 7, 8]
248
+ ```
249
+
250
+ #### `descendingLinear(from: number, to: number) => number[]`
251
+
252
+ ```js
253
+ descendingLinear(8, 1); // => [8, 7, 6, 5, 4, 3, 2, 1]
254
+ ```
255
+
256
+ #### `grouping(scaleLength: number, groupSize: number, step?: number) => number[]`
257
+
258
+ Generate overlapping groups:
259
+
260
+ ```js
261
+ grouping(7, 4); // => [1,2,3,4, 2,3,4,5, 3,4,5,6, 4,5,6,7]
262
+ ```
263
+
264
+ #### `thirds(scaleLength) / fourths(scaleLength) / sixths(scaleLength)`
265
+
266
+ Convenience wrappers:
267
+
268
+ ```js
269
+ thirds(7); // same as ascendingIntervals(7, 2)
270
+ fourths(7); // same as ascendingIntervals(7, 3)
271
+ sixths(7); // same as ascendingIntervals(7, 5)
272
+ ```
273
+
274
+ ### Pattern Walker
275
+
276
+ #### `walkPattern(scale: FrettedScale, pattern: number[], options?: WalkOptions) => FrettedNote[]`
277
+
278
+ Walk a degree pattern through a fretted scale, picking concrete notes:
279
+
280
+ ```js
281
+ const scale = buildFrettedScale(get("CAGED E Shape"), "A");
282
+ const notes = walkPattern(scale, [1, 3, 5, 7, 6, 5, 4, 3, 2, 1]);
283
+ ```
284
+
285
+ Options:
286
+ - `direction`: `"auto"` (default) — auto-detects ascending/descending from consecutive degrees. `"up"`, `"down"`, `"nearest"` for fixed direction.
287
+
288
+ Auto-direction compares consecutive pattern degrees: `[1,3,5,7]` ascends, then `[7,6,5,4,3,2,1]` descends. The walker picks the right octave at each step.
289
+
290
+ ### Sequences
291
+
292
+ #### `applySequence(scale: FrettedScale, sequence: number[], options?: SequenceOptions) => FrettedNote[][]`
293
+
294
+ Apply a degree sequence to a fretted scale, optionally shifting incrementally across degrees:
295
+
296
+ ```js
297
+ const passes = applySequence(scale, SEQ_1235, {
298
+ incremental: true, // shift pattern across each degree
299
+ boundToShape: true, // stop when notes go outside the shape
300
+ });
301
+ // Pass 1: [1,2,3,5], Pass 2: [2,3,4,6], Pass 3: [3,4,5,7], ...
302
+ ```
303
+
304
+ Options:
305
+ - `incremental` — shift pattern by +1 each pass (default: `false`)
306
+ - `boundToShape` — stop passes when notes exceed shape range (default: `true`)
307
+ - `startDegree` — starting degree (default: `1`)
308
+ - `passes` — max number of passes (default: all that fit)
309
+
310
+ #### `flattenSequence(passes: FrettedNote[][]) => FrettedNote[]`
311
+
312
+ Flatten multi-pass results into a single array:
313
+
314
+ ```js
315
+ const allNotes = flattenSequence(passes);
316
+ ```
317
+
318
+ #### Built-in Sequences
319
+
320
+ ```js
321
+ import {
322
+ ASCENDING_THIRDS, // [1,3, 2,4, 3,5, 4,6, 5,7, 6,8]
323
+ DESCENDING_THIRDS, // [8,6, 7,5, 6,4, 5,3, 4,2, 3,1]
324
+ SEQ_1235, // [1,2,3,5]
325
+ SEQ_1234_GROUP, // [1,2,3,4]
326
+ SEQ_UP_DOWN, // [1,2,3,4,3,2]
327
+ SEQ_TRIAD_CLIMB, // [1,3,5,3]
328
+ SEQ_1357_DESC, // [1,3,5,7,6,5,4,3,2,1]
329
+ } from "tonal-guitar";
330
+ ```
331
+
332
+ ### Notation
333
+
334
+ #### `parseChordFrets(input: string | (number | null)[]) => (number | null)[]`
335
+
336
+ Parse chord fret notation:
337
+
338
+ ```js
339
+ parseChordFrets("x32010"); // => [null, 3, 2, 0, 1, 0]
340
+ parseChordFrets("8-10-10-9-8-8"); // => [8, 10, 10, 9, 8, 8]
341
+ parseChordFrets("x-3-2-0-1-0"); // => [null, 3, 2, 0, 1, 0]
342
+ ```
343
+
344
+ #### `formatChordFrets(frets: (number | null)[]) => string`
345
+
346
+ Format fret array back to notation:
347
+
348
+ ```js
349
+ formatChordFrets([null, 3, 2, 0, 1, 0]); // => "x32010"
350
+ formatChordFrets([8, 10, 10, 9, 8, 8]); // => "8-10-10-9-8-8"
351
+ ```
352
+
353
+ #### `parseScalePattern(input: string) => number[][]`
354
+
355
+ Parse scale pattern shorthand:
356
+
357
+ ```js
358
+ parseScalePattern("5-8,5-7,5-7,5-7,5-8,5-8");
359
+ // => [[5,8],[5,7],[5,7],[5,7],[5,8],[5,8]]
360
+ ```
361
+
362
+ ### Output Formatters
363
+
364
+ #### `toAlphaTeX(notes: FrettedNote[], options?: AlphaTexOptions) => string`
365
+
366
+ Format notes as [AlphaTeX](https://www.alphatab.net/docs/alphatex/) notation:
367
+
368
+ ```js
369
+ toAlphaTeX(notes, {
370
+ title: "A Major Thirds",
371
+ tempo: 120,
372
+ duration: 8,
373
+ key: "A",
374
+ });
375
+ ```
376
+
377
+ Options:
378
+ - `title` — piece title (default: `"Exercise"`)
379
+ - `tempo` — BPM (default: `120`)
380
+ - `duration` — default note duration: `4`, `8`, `16` (default: `8`)
381
+ - `tuning` — override tuning (default: `STANDARD`)
382
+ - `key` — key signature (default: `"C"`)
383
+ - `timeSignature` — e.g. `[4, 4]`
384
+ - `notesPerBar` — notes per bar (default: derived from duration)
385
+ - `noteDurations` — per-note duration array
386
+ - `rhythmPattern` — repeating duration cycle, e.g. `[8, 8, 16, 16]`
387
+
388
+ #### `toAsciiTab(notes: FrettedNote[], options?: AsciiTabOptions) => string`
389
+
390
+ Format notes as ASCII tablature:
391
+
392
+ ```js
393
+ toAsciiTab(notes);
394
+ // e|---5----|
395
+ // B|-----5--|
396
+ // G|---6----|
397
+ // D|-----7--|
398
+ // A|---7----|
399
+ // E|-5------|
400
+ ```
401
+
402
+ ### Arpeggios & Chord Detection
403
+
404
+ These functions require `@tonaljs/chord` (optional peer dependency).
405
+
406
+ #### `arpeggioFromShape(shape: ScaleShape, chordName: string, parentRoot: string, tuning?: string[]) => FrettedScale`
407
+
408
+ Derive a chord-tone arpeggio from a scale shape. Builds the parent scale, then filters to notes whose pitch-class chroma belongs to the named chord.
409
+
410
+ ```js
411
+ import { arpeggioFromShape, get } from "tonal-guitar";
412
+
413
+ // Am7 arpeggio from the G Shape in the key of C major
414
+ const am7 = arpeggioFromShape(get("G Shape"), "Am7", "C");
415
+ // am7.root === "A"
416
+ // am7.scaleType === "minor seventh"
417
+ // am7.notes: 10 FrettedNotes, all with pc in {"A","C","E","G"}
418
+ // Each note's .interval is in the C-major (parent) frame, e.g. "6M" for A
419
+ ```
420
+
421
+ The returned notes carry their **parent-scale** `interval` and `degree` fields unchanged — the chord name determines which pitch classes are kept, but the notes still report their position within the parent scale.
422
+
423
+ #### `arpeggioFromScale(parent: FrettedScale, chordName: string) => FrettedScale`
424
+
425
+ Same as `arpeggioFromShape` but takes an already-built parent `FrettedScale`. Use this when you want to reuse a scale you have already built:
426
+
427
+ ```js
428
+ const cMajor = buildFrettedScale(get("G Shape"), "C");
429
+ const am7 = arpeggioFromScale(cMajor, "Am7");
430
+ const em7 = arpeggioFromScale(cMajor, "Em7");
431
+ ```
432
+
433
+ Bare chord types (no tonic) fall back to `parent.root`:
434
+
435
+ ```js
436
+ arpeggioFromScale(cMajor, "m7"); // tonic = "C"
437
+ ```
438
+
439
+ #### `filterChordTones(scale: FrettedScale, intervals: string[]) => FrettedScale`
440
+
441
+ Low-level parent-frame filter. Retains notes whose `interval` field (relative to the parent root) is in the provided set. Use this when you have already translated intervals to the parent frame, or when you want zero Tonal dependencies:
442
+
443
+ ```js
444
+ import { filterChordTones, buildFrettedScale, get } from "tonal-guitar";
445
+
446
+ // Am7 in C major, parent-frame intervals: A=6M, C=1P, E=3M, G=5P
447
+ const cMajor = buildFrettedScale(get("G Shape"), "C");
448
+ filterChordTones(cMajor, ["6M", "1P", "3M", "5P"]);
449
+ ```
450
+
451
+ #### `inferShapeContext(input: InferenceInput, options?: InferenceOptions) => InferenceCandidate[]`
452
+
453
+ Detect which registered scale shapes cover a given grip or arpeggio. Accepts a compact fret string, a fret array, or a `FrettedScale`:
454
+
455
+ ```js
456
+ import { inferShapeContext } from "tonal-guitar";
457
+
458
+ // From a chord grip
459
+ const candidates = inferShapeContext("x32010");
460
+ // candidates[0].shape — best matching ScaleShape
461
+ // candidates[0].shapeRoot — parent-scale root (e.g. "C")
462
+ // candidates[0].score — total weighted match score
463
+ // candidates[0].breakdown — transparent per-term breakdown
464
+
465
+ // From an arpeggio, filtered to CAGED system, top 3
466
+ const arp = arpeggioFromShape(get("G Shape"), "Am7", "C");
467
+ inferShapeContext(arp, { system: "caged", limit: 3 });
468
+ ```
469
+
470
+ Returns `[]` when fewer than 3 distinct pitch classes are present (use `{ includeWeak: true }` to override).
471
+
472
+ #### Strummed voicing rendering
473
+
474
+ Both `toAlphaTeX` and `toAsciiTab` now accept `FrettedNote[][]` — each inner array is one simultaneous beat (strum/chord):
475
+
476
+ ```js
477
+ import { applyChordShape, chordShapes, toAlphaTeX, toAsciiTab } from "tonal-guitar";
478
+
479
+ const voicing = applyChordShape(chordShapes.get("C Major Open"), "C");
480
+
481
+ // Render as strummed chord
482
+ toAlphaTeX([voicing.positions], { duration: 4 });
483
+ // => header + :4 (3.5 2.4 0.3 1.2 0.1) |
484
+
485
+ toAsciiTab([voicing.positions]);
486
+ // e|0|
487
+ // B|1|
488
+ // G|0|
489
+ // D|2|
490
+ // A|3|
491
+ // E|-|
492
+ ```
493
+
494
+ Flat `FrettedNote[]` (original form) is still accepted and produces identical output.
495
+
496
+ ### Tonal.js Integration
497
+
498
+ These functions require optional peer dependencies (`@tonaljs/scale`, `@tonaljs/chord`, `@tonaljs/key`).
499
+
500
+ #### `buildFromScale(shape: ScaleShape, scaleName: string, tuning?: string[]) => FrettedScale`
501
+
502
+ Build a fretted scale using Tonal's `Scale.get()` for validation. Populates `scaleType` and `scaleName`:
503
+
504
+ ```js
505
+ const scale = buildFromScale(get("CAGED E Shape"), "A major");
506
+ scale.scaleType; // => "major"
507
+ scale.scaleName; // => "A major"
508
+
509
+ buildFromScale(get("Pentatonic Box 1"), "A minor pentatonic");
510
+ ```
511
+
512
+ #### `relatedScales(frettedScale: FrettedScale) => Array<{ root: string, scale: string }>`
513
+
514
+ Find all modal relatives (scales sharing the same pitch classes):
515
+
516
+ ```js
517
+ const scale = buildFromScale(get("Pentatonic Box 1"), "A minor pentatonic");
518
+ relatedScales(scale);
519
+ // => [
520
+ // { root: "C", scale: "major pentatonic" },
521
+ // { root: "D", scale: "egyptian" },
522
+ // { root: "E", scale: "malkos raga" },
523
+ // { root: "G", scale: "ritusen" },
524
+ // { root: "A", scale: "minor pentatonic" }
525
+ // ]
526
+ ```
527
+
528
+ #### `identifyChord(frets: (number | null)[], tuning?: string[]) => string[]`
529
+
530
+ Identify chord names from fret positions:
531
+
532
+ ```js
533
+ identifyChord([null, 3, 2, 0, 1, 0]); // => ["C"]
534
+ identifyChord([0, 2, 2, 1, 0, 0]); // => ["E"]
535
+ ```
536
+
537
+ #### `analyzeInKey(frets: (number | null)[], keyName: string, tuning?: string[]) => KeyAnalysis`
538
+
539
+ Analyze a chord voicing in the context of a major key:
540
+
541
+ ```js
542
+ analyzeInKey([null, 3, 2, 0, 1, 0], "C");
543
+ // => { empty: false, chord: "C", numeral: "I", degree: 1 }
544
+
545
+ analyzeInKey([null, 3, 2, 0, 1, 0], "G");
546
+ // => { empty: false, chord: "C", numeral: "IV", degree: 4 }
547
+ ```
548
+
549
+ Returns `{ empty: true }` if the chord is not found in the key.
550
+
551
+ #### `isShapeCompatible(shape: ScaleShape, scaleName: string) => boolean`
552
+
553
+ Check if a shape's intervals are all present in a given scale:
554
+
555
+ ```js
556
+ isShapeCompatible(get("CAGED E Shape"), "A major"); // => true
557
+ isShapeCompatible(get("Pentatonic Box 1"), "A major"); // => true (subset)
558
+ ```
559
+
560
+ #### `modeShapes(modeName: string, shapeSystem?: string) => ScaleShape[]`
561
+
562
+ Get all registered shapes compatible with a mode/scale:
563
+
564
+ ```js
565
+ modeShapes("A major", "caged"); // all CAGED shapes that fit A major
566
+ modeShapes("A dorian"); // all shapes (any system) that fit A dorian
567
+ ```
568
+
569
+ ## Types
570
+
571
+ The package exports these TypeScript interfaces:
572
+
573
+ - `FrettedNote` — a note on the fretboard with position, pitch, and interval info
574
+ - `FrettedScale` — a scale applied to the fretboard (with `empty` sentinel pattern)
575
+ - `ScaleShape` — a scale shape definition (intervals per string)
576
+ - `ChordShape` — a chord voicing definition (one interval per string + fingerings + optional harmonic metadata)
577
+ - `Barre` — barre chord finger placement
578
+ - `Fingering` — chord shape applied to a specific root
579
+ - `FretboardPosition` — absolute position on the fretboard (string, fret, note, midi)
580
+ - `VoicingFamily` — voicing family enum (`"caged"`, `"shell"`, `"open"`, `"barre"`, etc.)
581
+ - `VoicingPatternDictionary` — dictionary type for voicing patterns (used by jazz shells)
582
+ - `InferenceInput` — input forms for `inferShapeContext`
583
+ - `InferenceOptions` — options for `inferShapeContext`
584
+ - `InferenceCandidate` — a ranked shape-detection result
585
+ - `InferenceProbe` — normalised internal probe used by the scoring core
586
+ - `ScoreBreakdown` — transparent per-term score breakdown on each `InferenceCandidate`
587
+ - `WalkOptions` — options for `walkPattern`
588
+ - `SequenceOptions` — options for `applySequence`
589
+ - `AlphaTexOptions` — options for `toAlphaTeX`
590
+ - `AsciiTabOptions` — options for `toAsciiTab`
591
+ - `KeyAnalysis` — result of `analyzeInKey`
592
+
593
+ ## Related
594
+
595
+ - [@tonaljs/scale](https://github.com/tonaljs/tonal/tree/main/packages/scale) — scale definitions and lookups
596
+ - [@tonaljs/chord](https://github.com/tonaljs/tonal/tree/main/packages/chord) — chord detection and properties
597
+ - [@tonaljs/mode](https://github.com/tonaljs/tonal/tree/main/packages/mode) — modal scale relationships
598
+ - [@tonaljs/key](https://github.com/tonaljs/tonal/tree/main/packages/key) — key signatures and analysis
599
+
600
+ ## License
601
+
602
+ MIT