musicvis-lib
Version:
Music analysis and visualization library
1,050 lines (852 loc) • 292 kB
Markdown
## Modules
<dl>
<dt><a href="#module_Alignment">Alignment</a></dt>
<dd></dd>
<dt><a href="#module_DiffAlignment">DiffAlignment</a></dt>
<dd></dd>
<dt><a href="#module_Chords">Chords</a></dt>
<dd></dd>
<dt><a href="#module_comparison/ErrorClassifier">comparison/ErrorClassifier</a></dt>
<dd></dd>
<dt><a href="#module_comparison/Matching">comparison/Matching</a></dt>
<dd></dd>
<dt><a href="#module_comparison/Similarity">comparison/Similarity</a></dt>
<dd></dd>
<dt><a href="#module_comparison/SimilarSections">comparison/SimilarSections</a></dt>
<dd></dd>
<dt><a href="#module_instruments/StringedFingering">instruments/StringedFingering</a></dt>
<dd></dd>
<dt><a href="#module_fileFormats/Midi">fileFormats/Midi</a></dt>
<dd><p>Lookup for many MIDI specifications.</p>
</dd>
<dt><a href="#module_fileFormats/MidiParser">fileFormats/MidiParser</a></dt>
<dd></dd>
<dt><a href="#module_fileFormats/MusicXmlParser">fileFormats/MusicXmlParser</a></dt>
<dd></dd>
<dt><a href="#module_graphics/Canvas">graphics/Canvas</a></dt>
<dd></dd>
<dt><a href="#module_Svg">Svg</a></dt>
<dd></dd>
<dt><a href="#module_musicvis-lib">musicvis-lib</a></dt>
<dd></dd>
<dt><a href="#module_input/AudioRecorder">input/AudioRecorder</a> ⇒ <code>Promise</code></dt>
<dd><p>Allows to record audio blobs.</p>
</dd>
<dt><a href="#module_input/MidiInputManager">input/MidiInputManager</a></dt>
<dd><p>Handles incoming MIDI messages from a MIDI device.</p>
</dd>
<dt><a href="#module_input/MidiRecorder">input/MidiRecorder</a> ⇒ <code>Promise</code></dt>
<dd><p>Records incoming MIDI messages from a MIDI device.</p>
</dd>
<dt><a href="#module_instruments/Drums">instruments/Drums</a></dt>
<dd></dd>
<dt><a href="#module_instruments/Guitar">instruments/Guitar</a></dt>
<dd></dd>
<dt><a href="#module_instruments/Lamellophone">instruments/Lamellophone</a></dt>
<dd></dd>
<dt><a href="#module_instruments/Piano">instruments/Piano</a></dt>
<dd></dd>
<dt><a href="#module_stringBased/Gotoh">stringBased/Gotoh</a></dt>
<dd></dd>
<dt><a href="#module_stringBased">stringBased</a></dt>
<dd></dd>
<dt><a href="#module_stringBased/Levenshtein">stringBased/Levenshtein</a></dt>
<dd></dd>
<dt><a href="#module_stringBased/LongestCommonSubsequence">stringBased/LongestCommonSubsequence</a></dt>
<dd></dd>
<dt><a href="#module_stringBased/NeedlemanWunsch">stringBased/NeedlemanWunsch</a></dt>
<dd></dd>
<dt><a href="#module_stringBased/SuffixTree">stringBased/SuffixTree</a></dt>
<dd></dd>
<dt><a href="#module_utils/ArrayUtils">utils/ArrayUtils</a></dt>
<dd></dd>
<dt><a href="#module_utils/BlobUtils">utils/BlobUtils</a></dt>
<dd></dd>
<dt><a href="#module_utils/FormattingUtils">utils/FormattingUtils</a></dt>
<dd></dd>
<dt><a href="#module_utils">utils</a></dt>
<dd></dd>
<dt><a href="#module_utils/LocalStorageUtils">utils/LocalStorageUtils</a></dt>
<dd></dd>
<dt><a href="#module_utils/MathUtils">utils/MathUtils</a></dt>
<dd></dd>
<dt><a href="#module_utils/MiscUtils">utils/MiscUtils</a></dt>
<dd></dd>
<dt><a href="#module_utils/MusicUtils">utils/MusicUtils</a></dt>
<dd></dd>
<dt><a href="#module_utils/NoteColorUtils">utils/NoteColorUtils</a></dt>
<dd></dd>
<dt><a href="#module_utils/RecordingsUtils">utils/RecordingsUtils</a></dt>
<dd></dd>
<dt><a href="#module_utils/StatisticsUtils">utils/StatisticsUtils</a></dt>
<dd></dd>
<dt><a href="#module_utils/WebMidiUtils">utils/WebMidiUtils</a></dt>
<dd></dd>
</dl>
## Classes
<dl>
<dt><a href="#GuitarNote">GuitarNote</a> ⇐ <code><a href="#Note">Note</a></code></dt>
<dd><p>Guitar note class that reflects MIDI properties but has
absolute start and end times in seconds and
information on how to play it.</p>
</dd>
<dt><a href="#HarmonicaNote">HarmonicaNote</a> ⇐ <code><a href="#Note">Note</a></code></dt>
<dd><p>Harmonica note class that reflects MIDI properties but has
absolute start and end times in seconds and
information on how to play it.</p>
</dd>
<dt><del><a href="#MusicPiece">MusicPiece</a></del></dt>
<dd><p>Represents a parsed MIDI or MusicXML file in a uniform format.</p>
</dd>
<dt><del><a href="#Track">Track</a></del></dt>
<dd><p>Used by MusicPiece, should not be used directly</p>
</dd>
<dt><a href="#TempoDefinition">TempoDefinition</a></dt>
<dd><p>Tempo definition</p>
</dd>
<dt><a href="#TimeSignature">TimeSignature</a></dt>
<dd><p>Time signature definition</p>
</dd>
<dt><a href="#KeySignature">KeySignature</a></dt>
<dd><p>Key signature definition</p>
</dd>
<dt><a href="#Note">Note</a></dt>
<dd><p>Note class that reflects MIDI properties but has
absolute start and end times in seconds.</p>
</dd>
<dt><a href="#NoteArray">NoteArray</a></dt>
<dd><p>This class represents an array of note objects.
It can be used to simplify operations on a track.</p>
</dd>
<dt><a href="#PitchBend">PitchBend</a></dt>
<dd><p>Class that allows to represent pitch-bends from a MIDI file</p>
</dd>
<dt><a href="#PitchSequence">PitchSequence</a></dt>
<dd><p>Stores a sequence of pitches and provides some methods to simplify and
manipulate it.</p>
</dd>
<dt><a href="#Recording">Recording</a></dt>
<dd><p>Class for storing recorded notes alongside meta information.</p>
</dd>
</dl>
## Constants
<dl>
<dt><a href="#drumInstrumentMap">drumInstrumentMap</a> : <code>Map.<string, object></code></dt>
<dd><p>Maps internal drum names to MusicXML instrument names and note display</p>
</dd>
<dt><a href="#patterns">patterns</a> : <code>Map.<string, object></code></dt>
<dd><p>Contains patterns for exercises, such as scales</p>
</dd>
<dt><a href="#patterns">patterns</a> : <code>Map.<string, object></code></dt>
<dd><p>Contains patterns for exercises, such as scales
TODO: find way to automatically compute patterns from scales, get scales from tonaljs</p>
</dd>
<dt><a href="#noteErrorTypes">noteErrorTypes</a> : <code>object</code></dt>
<dd></dd>
<dt><a href="#chordErrorTypes">chordErrorTypes</a> : <code>object</code></dt>
<dd></dd>
</dl>
## Functions
<dl>
<dt><a href="#priorityMatching">priorityMatching(itemsA, itemsB, distanceFunction)</a> ⇒ <code>Map.<number, number></code></dt>
<dd><p>Idea: Like in hierarchical clustering, take the most similar pair out of the
set of all possible pairs repeatedly, until one array of items is empty.</p>
</dd>
<dt><a href="#errorFromPriorityMatching">errorFromPriorityMatching(gtNotes, recNotes, distanceFunction)</a> ⇒ <code>Map.<Note, number></code></dt>
<dd><p>First matches GT to rec notes via priorityMatching, then computes the error
for each GT note that has been matched using the same distance function.
The Map will be undefined for GT notes that have not been matched, they can
be considered missing in the recording.</p>
</dd>
<dt><a href="#balancedNoteDistance">balancedNoteDistance(a, b)</a> ⇒ <code>number</code></dt>
<dd><p>Computes a distance (inverse similarity) of two notes, considering pitch,
chroma, start, duration, and channel.</p>
</dd>
<dt><a href="#getMatrixMinPosition">getMatrixMinPosition(matrix)</a> ⇒ <code>Array.<number></code></dt>
<dd><p>Returns the row and colum indices of the minimum value of the given matrix</p>
</dd>
<dt><a href="#generatePattern">generatePattern(patternType, [repeat])</a> ⇒ <code>Array.<Array.<number>></code></dt>
<dd><p>Takes a baseline pattern and moves it to the correct position on the fretboard</p>
</dd>
<dt><a href="#generateXml">generateXml(name, tempo, timeSig, drumHits)</a> ⇒ <code>string</code></dt>
<dd><p>Generates MusicXML text from a pattern</p>
</dd>
<dt><a href="#generatePattern">generatePattern(patternType, rootNote, [repeat], [alternate])</a> ⇒ <code>Array.<Array.<number>></code></dt>
<dd><p>Takes a baseline pattern and moves it to the correct position on the fretboard</p>
</dd>
<dt><a href="#generateXml">generateXml(name, tempo, timeSig, positions)</a> ⇒ <code>string</code></dt>
<dd><p>Generates MusicXML text from a pattern</p>
</dd>
<dt><a href="#generatePattern">generatePattern(patternType, [rootNote], [scaleType], [repeat], [alternate])</a> ⇒ <code>Array.<Array.<number>></code></dt>
<dd><p>Takes a baseline pattern and moves it to the correct position on the fretboard</p>
</dd>
<dt><a href="#repeatPattern">repeatPattern(nRepetitions, pattern, alternate)</a> ⇒ <code>Array</code></dt>
<dd><p>Repeats a pattern with or without alternating direction</p>
</dd>
<dt><a href="#generateXml">generateXml(name, tempo, timeSig, notes)</a> ⇒ <code>string</code></dt>
<dd><p>Generates MusicXML text from a pattern</p>
</dd>
<dt><a href="#getStartTimeErrorPerGtNote">getStartTimeErrorPerGtNote(gtNotes, recNotes)</a> ⇒ <code>Array.<number></code></dt>
<dd><p>Takes the ground truth and a single recording.
Both gtNotes and recNotes must be sorted by note start time ascending.</p>
</dd>
<dt><a href="#getNoteErrors">getNoteErrors(expectedNote, actualNote)</a> ⇒ <code>Array.<string></code></dt>
<dd></dd>
<dt><a href="#getChordErrors">getChordErrors(expectedChord, actualChord)</a> ⇒ <code>Array.<string></code></dt>
<dd></dd>
<dt><a href="#noteCountDifference">noteCountDifference(notesA, notesB)</a> ⇒ <code>number</code></dt>
<dd></dd>
<dt><a href="#durationDifference">durationDifference(notesA, notesB)</a> ⇒ <code>number</code></dt>
<dd></dd>
<dt><a href="#pitchHistogramDistance">pitchHistogramDistance(notesA, notesB)</a> ⇒ <code>number</code></dt>
<dd></dd>
<dt><a href="#timeBinningDistance">timeBinningDistance(notesA, notesB, binSize)</a> ⇒ <code>number</code></dt>
<dd></dd>
<dt><a href="#timeBinningDistance2">timeBinningDistance2(notesA, notesB, binSize)</a> ⇒ <code>number</code></dt>
<dd></dd>
<dt><a href="#notesCount">notesCount(notes)</a> ⇒ <code>number</code></dt>
<dd><p>Computes the number of notes</p>
</dd>
<dt><a href="#duration">duration(notes)</a> ⇒ <code>number</code></dt>
<dd><p>Computes played duration</p>
</dd>
<dt><a href="#notesPerSecond">notesPerSecond(notes)</a> ⇒ <code>number</code></dt>
<dd><p>Computes the number of notes played per second</p>
</dd>
<dt><a href="#notesPerBeat">notesPerBeat(notes, [bpm])</a> ⇒ <code>number</code></dt>
<dd><p>Computes the number of notes played per relative time (beat)</p>
</dd>
<dt><a href="#differentNotesUsed">differentNotesUsed(notes, mode)</a> ⇒ <code>Array.<object></code></dt>
<dd><p>Computes the number of different notes used in different modi.</p>
<ul>
<li>Pitch: note and octave are considered</li>
<li>Chroma: only note without octave considered, e.g., C4 == C5</li>
<li>Fretboard position: tuple (string, fret) will be compared</li>
</ul>
</dd>
<dt><a href="#ratioNotesInSet">ratioNotesInSet(notes, set)</a> ⇒ <code>number</code></dt>
<dd><p>Computes the ratio of notes that are in the given set.
Can be used for checking how many notes that were played are part of a
musical scale, by passing the notes of this scale as set.</p>
</dd>
<dt><a href="#pitchMeanAndVariance">pitchMeanAndVariance(notes)</a> ⇒ <code>object</code></dt>
<dd><p>Computes the mean and variance of played pitches</p>
</dd>
<dt><a href="#pitchExtent">pitchExtent(notes)</a> ⇒ <code>Array.<number></code></dt>
<dd><p>Computes the min and max pitch</p>
</dd>
<dt><a href="#intervalMeanAndVariance">intervalMeanAndVariance(notes)</a> ⇒ <code>object</code></dt>
<dd><p>Computes the mean and variance of played intervals</p>
</dd>
<dt><a href="#dynamicsMeanAndVariance">dynamicsMeanAndVariance(notes)</a> ⇒ <code>object</code></dt>
<dd><p>Computes the mean and variance of played dynamics</p>
</dd>
<dt><a href="#durationMeanAndVariance">durationMeanAndVariance(notes)</a> ⇒ <code>object</code></dt>
<dd><p>Computes the mean and variance of played dynamics</p>
</dd>
<dt><a href="#onsetDiffMeanAndVariance">onsetDiffMeanAndVariance(notes)</a> ⇒ <code>object</code></dt>
<dd><p>Computes the mean and variance of onset (start time) differences between
consecutive notes.</p>
</dd>
<dt><a href="#guitarStringSkips">guitarStringSkips(notes, [skipped])</a> ⇒ <code>number</code></dt>
<dd><p>Computs the ratio of notes for which one string (or more) where skipped
between the one before and the current note.
The <code>skipped</code> parameter set the minimum amount of strings between the two
notes, e.g., going from string 1 to 3 means that one (string 2) was skipped.</p>
</dd>
<dt><a href="#guitarFretSkips">guitarFretSkips(notes, [skipped])</a> ⇒ <code>number</code></dt>
<dd><p>Computs the ratio of notes for which one fret (or more) where skipped between
the one before and the current note.
The <code>skipped</code> parameter set the minimum amount of fret between the two
notes, e.g., going from fret 1 to 3 means that one (fret 2) was skipped.</p>
</dd>
<dt><a href="#harmonySizeDistribution">harmonySizeDistribution(harmonies)</a> ⇒ <code>Array.<object></code></dt>
<dd><p>Counts how often harmonies of different sizes occur</p>
</dd>
<dt><a href="#harmonySingleToMultiRatio">harmonySingleToMultiRatio(harmonies)</a> ⇒ <code>number</code></dt>
<dd><p>Determines the ratio of single notes to multi-note harmonies</p>
</dd>
<dt><a href="#notesToIntervals">notesToIntervals(notes)</a> ⇒ <code>Array.<number></code></dt>
<dd><p>Computes the pitch intervals between consecutive notes</p>
</dd>
<dt><a href="#notesToOnsetDifferences">notesToOnsetDifferences(notes)</a> ⇒ <code>Array.<number></code></dt>
<dd><p>Computes the start time differences between consecutive notes</p>
</dd>
<dt><a href="#compress">compress(sequence)</a> ⇒ <code>object</code></dt>
<dd><p>Compresses a sequence by detecting immediately repeating subsequences
hierarchically. Optimal result but high performance complexity.</p>
</dd>
<dt><a href="#getImmediateRepetitions">getImmediateRepetitions(sequence)</a> ⇒ <code>Array.<object></code></dt>
<dd><p>Finds all immediate repetitions in a given sequence.</p>
</dd>
<dt><a href="#decompress">decompress(tree)</a> ⇒ <code>Array</code></dt>
<dd><p>Restores the original array/sequence from the compressed hierarchy.</p>
</dd>
<dt><a href="#summary">summary(tree)</a> ⇒ <code>Array</code></dt>
<dd><p>Returns the summary of a hierachy, leaving out information about repetitions.</p>
</dd>
<dt><a href="#toString">toString(tree, separator)</a> ⇒ <code>string</code></dt>
<dd><p>Formats a compressed hierarchy into a readable string, for example:
"1222333222333" => "1 (2x (3x 2) (3x 3))"</p>
</dd>
<dt><a href="#compressionRate">compressionRate(compressed)</a> ⇒ <code>number</code></dt>
<dd><p>Calculates the compression rate in [0, 1] for a result of compress().</p>
</dd>
<dt><a href="#getNGrams">getNGrams(string, length)</a> ⇒ <code>Map.<string, number></code></dt>
<dd><p>Calculates all n-grams with a specified length</p>
</dd>
<dt><a href="#getNGramsForArray">getNGramsForArray(array, length)</a> ⇒ <code>Map.<string, object></code></dt>
<dd><p>Calculates all n-grams with a specified length</p>
</dd>
<dt><a href="#simplify">simplify(objectArray, keys)</a></dt>
<dd><p>Simplifies each object in an array by copying only some keys and their values</p>
</dd>
<dt><a href="#getMusicPiecesFromBothFormats">getMusicPiecesFromBothFormats(fileBaseName)</a> ⇒ <code>Object</code></dt>
<dd><p>Given a file name (without extension), this function will read a .mid and a
.musicxml file and parse both to a MusicPiece before returning those.</p>
</dd>
<dt><a href="#getColorLightness">getColorLightness(color)</a> ⇒ <code>number</code></dt>
<dd><p>Determines the perceptual lightness of an HTML color</p>
</dd>
<dt><a href="#averageColor">averageColor(colors)</a> ⇒ <code>string</code></dt>
<dd><p>Determines the average of mutliple given colors</p>
</dd>
<dt><a href="#setOpacity">setOpacity(color, [opacity])</a> ⇒ <code>string</code></dt>
<dd><p>Sets a color's opacity.
Does not support colors in rgba format.</p>
</dd>
<dt><a href="#setSaturation">setSaturation(color, [saturation])</a> ⇒ <code>string</code></dt>
<dd><p>Sets a color's saturation.
Does not support colors in rgba format.</p>
</dd>
</dl>
<a name="module_Alignment"></a>
## Alignment
* [Alignment](#module_Alignment)
* _static_
* [.alignNoteArrays(gt, rec)](#module_Alignment.alignNoteArrays) ⇒ [<code>NoteArray</code>](#NoteArray)
* [.alignNoteArrays2(gt, rec)](#module_Alignment.alignNoteArrays2) ⇒ [<code>NoteArray</code>](#NoteArray)
* [.alignNoteArrays3(gt, rec)](#module_Alignment.alignNoteArrays3) ⇒ [<code>NoteArray</code>](#NoteArray)
* [.testAlignment()](#module_Alignment.testAlignment)
* [.alignmentBenchmark()](#module_Alignment.alignmentBenchmark)
* _inner_
* [~alignmentForce(a, b)](#module_Alignment..alignmentForce) ⇒ <code>number</code>
<a name="module_Alignment.alignNoteArrays"></a>
### Alignment.alignNoteArrays(gt, rec) ⇒ [<code>NoteArray</code>](#NoteArray)
Given two NoteArrays, shift the second one in time such that they are aligned
**Kind**: static method of [<code>Alignment</code>](#module_Alignment)
**Returns**: [<code>NoteArray</code>](#NoteArray) - an aligned copy of b
**Todo**
- [ ] use https://en.wikipedia.org/wiki/Smith%E2%80%93Waterman_algorithm
to find note alignment, then only use those for force calculation
| Param | Type | Description |
| --- | --- | --- |
| gt | [<code>NoteArray</code>](#NoteArray) | a NoteArray, e.g. the ground truth |
| rec | [<code>NoteArray</code>](#NoteArray) | a NoteArray to align to a |
<a name="module_Alignment.alignNoteArrays2"></a>
### Alignment.alignNoteArrays2(gt, rec) ⇒ [<code>NoteArray</code>](#NoteArray)
Given two NoteArrays, shift the second one in time such that they are aligned
**Kind**: static method of [<code>Alignment</code>](#module_Alignment)
**Returns**: [<code>NoteArray</code>](#NoteArray) - an aligned copy of b
| Param | Type | Description |
| --- | --- | --- |
| gt | [<code>NoteArray</code>](#NoteArray) | a NoteArray, e.g. the ground truth |
| rec | [<code>NoteArray</code>](#NoteArray) | a NoteArray to align to a |
<a name="module_Alignment.alignNoteArrays3"></a>
### Alignment.alignNoteArrays3(gt, rec) ⇒ [<code>NoteArray</code>](#NoteArray)
Given two NoteArrays, shift the second one in time such that they are aligned
**Kind**: static method of [<code>Alignment</code>](#module_Alignment)
**Returns**: [<code>NoteArray</code>](#NoteArray) - an aligned copy of b
**Todo**
- [ ] use median instead of average?
| Param | Type | Description |
| --- | --- | --- |
| gt | [<code>NoteArray</code>](#NoteArray) | a NoteArray, e.g. the ground truth |
| rec | [<code>NoteArray</code>](#NoteArray) | a NoteArray to align to a |
<a name="module_Alignment.testAlignment"></a>
### Alignment.testAlignment()
Test function
**Kind**: static method of [<code>Alignment</code>](#module_Alignment)
**Todo**
- [ ] move to test
<a name="module_Alignment.alignmentBenchmark"></a>
### Alignment.alignmentBenchmark()
**Kind**: static method of [<code>Alignment</code>](#module_Alignment)
**Todo**
- [ ] Benchmark different aligment functions on a randomly generated test set
This allows to check the calculated alignment against a known ground truth
<a name="module_Alignment..alignmentForce"></a>
### Alignment~alignmentForce(a, b) ⇒ <code>number</code>
Calculates the mean difference between all notes in a and the nearest same-
pitched notes in b
**Kind**: inner method of [<code>Alignment</code>](#module_Alignment)
**Returns**: <code>number</code> - mean time difference
| Param | Type | Description |
| --- | --- | --- |
| a | [<code>Array.<Note></code>](#Note) | array with notes |
| b | [<code>Array.<Note></code>](#Note) | array with notes |
<a name="module_DiffAlignment"></a>
## DiffAlignment
* [DiffAlignment](#module_DiffAlignment)
* [.alignRecordingToBestFit(gtNotes, recording, binSize)](#module_DiffAlignment.alignRecordingToBestFit) ⇒ [<code>Recording</code>](#Recording)
* [.alignRecordingSectionsToBestFit(gtNotes, recording, binSize, gapDuration, gapMode)](#module_DiffAlignment.alignRecordingSectionsToBestFit) ⇒ [<code>Recording</code>](#Recording)
* [.alignGtAndRecToMinimizeDiffError(gtNotes, recNotes, binSize)](#module_DiffAlignment.alignGtAndRecToMinimizeDiffError) ⇒ <code>Array.<object></code>
* [.activationMap(allNotes, binSize)](#module_DiffAlignment.activationMap) ⇒ <code>Map</code>
* [.agreement(gtActivations, recActivations, offset)](#module_DiffAlignment.agreement) ⇒ <code>number</code>
<a name="module_DiffAlignment.alignRecordingToBestFit"></a>
### DiffAlignment.alignRecordingToBestFit(gtNotes, recording, binSize) ⇒ [<code>Recording</code>](#Recording)
Aligns the recording to the best fitting position of the ground truth
**Kind**: static method of [<code>DiffAlignment</code>](#module_DiffAlignment)
**Returns**: [<code>Recording</code>](#Recording) - aligned recording
| Param | Type | Description |
| --- | --- | --- |
| gtNotes | [<code>Array.<Note></code>](#Note) | ground truth notes |
| recording | [<code>Recording</code>](#Recording) | a Recording object |
| binSize | <code>number</code> | time bin size in milliseconds |
<a name="module_DiffAlignment.alignRecordingSectionsToBestFit"></a>
### DiffAlignment.alignRecordingSectionsToBestFit(gtNotes, recording, binSize, gapDuration, gapMode) ⇒ [<code>Recording</code>](#Recording)
Splits the recording at gaps > gapDuration and then aligns each section to
the best fitting position of the ground truth.
**Kind**: static method of [<code>DiffAlignment</code>](#module_DiffAlignment)
**Returns**: [<code>Recording</code>](#Recording) - aligned recording
| Param | Type | Description |
| --- | --- | --- |
| gtNotes | [<code>Array.<Note></code>](#Note) | ground truth notes |
| recording | [<code>Recording</code>](#Recording) | a Recording object |
| binSize | <code>number</code> | time bin size in milliseconds |
| gapDuration | <code>number</code> | duration of seconds for a gap to be used as segmenting time |
| gapMode | <code>'start-start'</code> \| <code>'end-start'</code> | gaps can either be considered as the maximum time between two note's starts or the end of the first and the start of the second note |
<a name="module_DiffAlignment.alignGtAndRecToMinimizeDiffError"></a>
### DiffAlignment.alignGtAndRecToMinimizeDiffError(gtNotes, recNotes, binSize) ⇒ <code>Array.<object></code>
Global alignment.
Returns an array with matches sorted by magnitude of agreement.
The offsetMilliseconds value describes at what time the first note of the
recording should start.
Goal: Know which part of ground truth (GT) was played in recording (rec)
Assumptions:
- Rec has same tempo as GT
- Rec does not start before GT
- Rec does not repeat something that is not repeated in the GT
- Rec does not have gaps
Ideas:
- Brute-force
- Sliding window
- Using diff between time-pitch matrix of GT and rec
- Only compute agreement (correct diff part) for the current overlap
- For each time position save the agreement magnitude
- Optionally: repeat around local maxima with finer binSize
**Kind**: static method of [<code>DiffAlignment</code>](#module_DiffAlignment)
**Returns**: <code>Array.<object></code> - best offsets with agreements
| Param | Type | Description |
| --- | --- | --- |
| gtNotes | [<code>Array.<Note></code>](#Note) | ground truth notes |
| recNotes | [<code>Array.<Note></code>](#Note) | recorded notes |
| binSize | <code>number</code> | time bin size in milliseconds |
<a name="module_DiffAlignment.activationMap"></a>
### DiffAlignment.activationMap(allNotes, binSize) ⇒ <code>Map</code>
Returns an activation map, that maps pitch to an array of time bins.
Each bin contains a 0 when there is no note or a 1 when there is one.
**Kind**: static method of [<code>DiffAlignment</code>](#module_DiffAlignment)
**Returns**: <code>Map</code> - activation map
| Param | Type | Description |
| --- | --- | --- |
| allNotes | [<code>Array.<Note></code>](#Note) | notes |
| binSize | <code>number</code> | time bin size in milliseconds |
<a name="module_DiffAlignment.agreement"></a>
### DiffAlignment.agreement(gtActivations, recActivations, offset) ⇒ <code>number</code>
Given two activation maps, simply counts the number of bins [pitch, time]
where both have a 1, so an acitve note
GT must be longer than rec
**Kind**: static method of [<code>DiffAlignment</code>](#module_DiffAlignment)
**Returns**: <code>number</code> - agreement
**Todo**
- [ ] also count common 0s?
| Param | Type | Description |
| --- | --- | --- |
| gtActivations | <code>Map</code> | see activationMap() |
| recActivations | <code>Map</code> | see activationMap() |
| offset | <code>number</code> | offset for activation2 when comparing |
<a name="module_Chords"></a>
## Chords
* [Chords](#module_Chords)
* [.detectChordsByExactStart(notes)](#module_Chords.detectChordsByExactStart) ⇒ <code>Array.<Array.<Note>></code>
* [.detectChordsBySimilarStart(notes, threshold)](#module_Chords.detectChordsBySimilarStart) ⇒ <code>Array.<Array.<Note>></code>
* [.detectChordsByOverlap(notes, sortByPitch)](#module_Chords.detectChordsByOverlap) ⇒ <code>Array.<Array.<Note>></code>
* [.getChordType(notes)](#module_Chords.getChordType) ⇒ <code>string</code>
* [.getChordName(notes)](#module_Chords.getChordName) ⇒ <code>Array.<string></code>
<a name="module_Chords.detectChordsByExactStart"></a>
### Chords.detectChordsByExactStart(notes) ⇒ <code>Array.<Array.<Note>></code>
Detects chords as those notes that have the exact same start time, only works
for ground truth (since recordings are not exact)
Does only work if ground truth is aligned! TuxGuitar produces unaligned MIDI.
**Kind**: static method of [<code>Chords</code>](#module_Chords)
**Returns**: <code>Array.<Array.<Note>></code> - array of chord arrays
| Param | Type | Description |
| --- | --- | --- |
| notes | [<code>Array.<Note></code>](#Note) | notes |
<a name="module_Chords.detectChordsBySimilarStart"></a>
### Chords.detectChordsBySimilarStart(notes, threshold) ⇒ <code>Array.<Array.<Note>></code>
Detects chords by taking a note as new chord then adding all notes close
after it to the chord, until the next note is farther away than the given
`threshold`. Then, the next chord is started with this note.
**Kind**: static method of [<code>Chords</code>](#module_Chords)
**Returns**: <code>Array.<Array.<Note>></code> - chords
| Param | Type | Description |
| --- | --- | --- |
| notes | [<code>Array.<Note></code>](#Note) | notes |
| threshold | <code>number</code> | threshold |
<a name="module_Chords.detectChordsByOverlap"></a>
### Chords.detectChordsByOverlap(notes, sortByPitch) ⇒ <code>Array.<Array.<Note>></code>
Detects chords, by simply looking for notes that overlap each other in time.
Example:
=======
=========
========
Important: Notes must be sorted by start time for this to work correctly.
**Kind**: static method of [<code>Chords</code>](#module_Chords)
**Returns**: <code>Array.<Array.<Note>></code> - array of chord arrays
**Todo**
- [ ] not used yet
- [ ] optional minimum overlap ratio
- [ ] new definition of chord? i.e. notes have to start 'together'
| Param | Type | Description |
| --- | --- | --- |
| notes | [<code>Array.<Note></code>](#Note) | array of Note objects |
| sortByPitch | <code>boolean</code> | sort chords by pitch? (otherwise sorted by note start time) |
<a name="module_Chords.getChordType"></a>
### Chords.getChordType(notes) ⇒ <code>string</code>
Returns chord type, e.g. 'Major', 'Diminished', ...
Important: Notes must be sorted by pitch ascending
**Kind**: static method of [<code>Chords</code>](#module_Chords)
**Returns**: <code>string</code> - chord type
**Todo**
- [ ] some chords might be multiple types
| Param | Type | Description |
| --- | --- | --- |
| notes | [<code>Array.<Note></code>](#Note) | notes (sorted by pitch asc.) |
<a name="module_Chords.getChordName"></a>
### Chords.getChordName(notes) ⇒ <code>Array.<string></code>
https://github.com/tonaljs/tonal/tree/master/packages/chord
Detected chords can be used with https://github.com/tonaljs/tonal/tree/master/packages/chord-type
**Kind**: static method of [<code>Chords</code>](#module_Chords)
**Returns**: <code>Array.<string></code> - possible chord types
| Param | Type | Description |
| --- | --- | --- |
| notes | [<code>Array.<Note></code>](#Note) | notes |
<a name="module_comparison/ErrorClassifier"></a>
## comparison/ErrorClassifier
* [comparison/ErrorClassifier](#module_comparison/ErrorClassifier)
* _static_
* [.classifyErrors(gtNotes, recNotes, groupBy, threshold)](#module_comparison/ErrorClassifier.classifyErrors) ⇒ <code>Array.<NoteWithState></code>
* [.separateMissed(classifiedNotes)](#module_comparison/ErrorClassifier.separateMissed) ⇒ <code>Object</code>
* _inner_
* [~setOrAdd(map, key, value)](#module_comparison/ErrorClassifier..setOrAdd)
* [~hasAtLeastOne(map, key)](#module_comparison/ErrorClassifier..hasAtLeastOne) ⇒ <code>boolean</code>
<a name="module_comparison/ErrorClassifier.classifyErrors"></a>
### comparison/ErrorClassifier.classifyErrors(gtNotes, recNotes, groupBy, threshold) ⇒ <code>Array.<NoteWithState></code>
Compares a single recording to a ground truth and labels notes as missing,
extra, early/late, or short/long
**Kind**: static method of [<code>comparison/ErrorClassifier</code>](#module_comparison/ErrorClassifier)
**Returns**: <code>Array.<NoteWithState></code> - classified notes
**Todo**
- [ ] generalize to channel/pitch instead of string and fret?
| Param | Type | Description |
| --- | --- | --- |
| gtNotes | [<code>Array.<Note></code>](#Note) \| [<code>Array.<GuitarNote></code>](#GuitarNote) | ground truth notes |
| recNotes | [<code>Array.<Note></code>](#Note) \| [<code>Array.<GuitarNote></code>](#GuitarNote) | recordings notes |
| groupBy | <code>string</code> | attribute to group notes by |
| threshold | <code>number</code> | time threshold for same-ness |
<a name="module_comparison/ErrorClassifier.separateMissed"></a>
### comparison/ErrorClassifier.separateMissed(classifiedNotes) ⇒ <code>Object</code>
Separates classified GT and rec notes
**Kind**: static method of [<code>comparison/ErrorClassifier</code>](#module_comparison/ErrorClassifier)
**Returns**: <code>Object</code> - separated notes
| Param | Type | Description |
| --- | --- | --- |
| classifiedNotes | <code>Array.<NoteWithState></code> | classified notes |
<a name="module_comparison/ErrorClassifier..setOrAdd"></a>
### comparison/ErrorClassifier~setOrAdd(map, key, value)
**Kind**: inner method of [<code>comparison/ErrorClassifier</code>](#module_comparison/ErrorClassifier)
| Param | Type | Description |
| --- | --- | --- |
| map | <code>Map</code> | map |
| key | <code>\*</code> | key |
| value | <code>\*</code> | value |
<a name="module_comparison/ErrorClassifier..hasAtLeastOne"></a>
### comparison/ErrorClassifier~hasAtLeastOne(map, key) ⇒ <code>boolean</code>
**Kind**: inner method of [<code>comparison/ErrorClassifier</code>](#module_comparison/ErrorClassifier)
**Returns**: <code>boolean</code> - true if map.get(key).size > 0
| Param | Type | Description |
| --- | --- | --- |
| map | <code>Map</code> | map |
| key | <code>\*</code> | key |
<a name="module_comparison/Matching"></a>
## comparison/Matching
* [comparison/Matching](#module_comparison/Matching)
* [.matchGtAndRecordingNotes(recNotes, gtNotes)](#module_comparison/Matching.matchGtAndRecordingNotes) ⇒ <code>Map</code>
* [.matchGtAndMultipleRecordings(recordings, gtNotes)](#module_comparison/Matching.matchGtAndMultipleRecordings) ⇒ <code>Map</code>
* [.getMultiMatchingErrorPerNote(multiMatching, errorThreshold)](#module_comparison/Matching.getMultiMatchingErrorPerNote) ⇒ <code>Map</code>
* [.getMatchingError(matching, addPenalty, missPenalty, timingPenalty, timeThreshold)](#module_comparison/Matching.getMatchingError) ⇒ <code>object</code>
* [.getMatchingSection(matching, start, end)](#module_comparison/Matching.getMatchingSection) ⇒ <code>Map</code>
* [.getMatchingSliceError(matching, start, end, addPenalty, missPenalty, timingPenalty)](#module_comparison/Matching.getMatchingSliceError) ⇒ <code>object</code>
<a name="module_comparison/Matching.matchGtAndRecordingNotes"></a>
### comparison/Matching.matchGtAndRecordingNotes(recNotes, gtNotes) ⇒ <code>Map</code>
For one recording, separately for each pitch,
matches each recorded note to its closest ground truth note.
If there are multiple matches, the best (smallest time difference)
will be kept and others will be regarded as additional notes.
Ground truth notes without match will be regarded as missing notes.
Result format (separated by pitch in a Map):
Map:pitch->{
gtRecMap matched rec. note for each GT note Map:gtNoteStart->recNote,
additionalNotes: rec. notes without matched GT note
missingNotes: GT notes without matched rec. note
gtNotes: all GT notes
}
**Kind**: static method of [<code>comparison/Matching</code>](#module_comparison/Matching)
**Returns**: <code>Map</code> - result
**Todo**
- [ ] add max distance?
| Param | Type | Description |
| --- | --- | --- |
| recNotes | [<code>Array.<Note></code>](#Note) | recorded notes of a single recording |
| gtNotes | [<code>Array.<Note></code>](#Note) | ground truth notes |
<a name="module_comparison/Matching.matchGtAndMultipleRecordings"></a>
### comparison/Matching.matchGtAndMultipleRecordings(recordings, gtNotes) ⇒ <code>Map</code>
Matches all recorded notes from multiple recordings to the nearest
ground truth (GT) note.
Contrary to the matching created by matchGtAndRecordingNotes()
missing and additional notes are not considered, so multiple notes
from a single recording can be matched to the same GT note.
Result format:
Map:pitch->Map:gtStart->arrayOfMatchedRecNotes
**Kind**: static method of [<code>comparison/Matching</code>](#module_comparison/Matching)
**Returns**: <code>Map</code> - matching
| Param | Type | Description |
| --- | --- | --- |
| recordings | [<code>Array.<Recording></code>](#Recording) | recordings |
| gtNotes | [<code>Array.<Note></code>](#Note) | ground truth notes |
<a name="module_comparison/Matching.getMultiMatchingErrorPerNote"></a>
### comparison/Matching.getMultiMatchingErrorPerNote(multiMatching, errorThreshold) ⇒ <code>Map</code>
Calculates (for each pitch) the average error for each GT note (averaged
over all matched notes in the recordings),
as well as the maximum of all those average errors.
GT notes that have no matched recorded notes will have an error of 0.
**Kind**: static method of [<code>comparison/Matching</code>](#module_comparison/Matching)
**Returns**: <code>Map</code> - error summary Map:pitch->{gtErrorMap, maxError},
gtErrorMap is Map:gtStart->error (error is average over all time
differences between the GT note and matched recNotes)
| Param | Type | Description |
| --- | --- | --- |
| multiMatching | <code>Map</code> | matching with a GT and multiple recordings |
| errorThreshold | <code>number</code> | number seconds of deviation above which to exclude an error |
<a name="module_comparison/Matching.getMatchingError"></a>
### comparison/Matching.getMatchingError(matching, addPenalty, missPenalty, timingPenalty, timeThreshold) ⇒ <code>object</code>
Calculates the error of a matching by applying penalties and summing up
**Kind**: static method of [<code>comparison/Matching</code>](#module_comparison/Matching)
**Returns**: <code>object</code> - errors by category
| Param | Type | Description |
| --- | --- | --- |
| matching | <code>Map</code> | a matching created by matchGtAndRecordingNotes |
| addPenalty | <code>number</code> | penalty for each additonal note |
| missPenalty | <code>number</code> | penalty for each missing note |
| timingPenalty | <code>number</code> | penalty for note timing differences in seconds |
| timeThreshold | <code>number</code> | timing errors below it (absolute) are ignored |
<a name="module_comparison/Matching.getMatchingSection"></a>
### comparison/Matching.getMatchingSection(matching, start, end) ⇒ <code>Map</code>
Cuts a section from a matching by filtering on the start times
of ground truth, missing, and additonal notes
**Kind**: static method of [<code>comparison/Matching</code>](#module_comparison/Matching)
**Returns**: <code>Map</code> - section of matching
| Param | Type | Description |
| --- | --- | --- |
| matching | <code>Map</code> | matching |
| start | <code>number</code> | start time (inclusive) |
| end | <code>number</code> | end time (exclusive) |
<a name="module_comparison/Matching.getMatchingSliceError"></a>
### comparison/Matching.getMatchingSliceError(matching, start, end, addPenalty, missPenalty, timingPenalty) ⇒ <code>object</code>
Shortcut for getMatchingSection and getMatchingError,
see them for parameter details.
**Kind**: static method of [<code>comparison/Matching</code>](#module_comparison/Matching)
**Returns**: <code>object</code> - error by category
| Param | Type | Description |
| --- | --- | --- |
| matching | <code>Map</code> | matching |
| start | <code>number</code> | start time (inclusive) |
| end | <code>number</code> | end time (exclusive) |
| addPenalty | <code>number</code> | penalty for each additonal note |
| missPenalty | <code>number</code> | penalty for each missing note |
| timingPenalty | <code>number</code> | penalty for note timing differences in seconds |
<a name="module_comparison/Similarity"></a>
## comparison/Similarity
* [comparison/Similarity](#module_comparison/Similarity)
* _static_
* [.getSimilarParts(track, selectedInterval, stride, threshold, secondsPerBin, distance)](#module_comparison/Similarity.getSimilarParts) ⇒ <code>object</code>
* [.getTrackSimilarity(discrA, discrB, distance)](#module_comparison/Similarity.getTrackSimilarity) ⇒ <code>number</code>
* [.discretizeTime(track, secondsPerBin)](#module_comparison/Similarity.discretizeTime) ⇒ <code>Map</code>
* _inner_
* [~countActiveNoteBins(binArray)](#module_comparison/Similarity..countActiveNoteBins) ⇒ <code>number</code>
* [~sliceDiscretizedTrack(trackMap, startBin, endBin)](#module_comparison/Similarity..sliceDiscretizedTrack) ⇒ <code>Map</code>
* [~euclideanDistanceSquared(A, B)](#module_comparison/Similarity..euclideanDistanceSquared) ⇒ <code>number</code>
* [~neirestNeighborDistance(A, B)](#module_comparison/Similarity..neirestNeighborDistance) ⇒ <code>number</code>
<a name="module_comparison/Similarity.getSimilarParts"></a>
### comparison/Similarity.getSimilarParts(track, selectedInterval, stride, threshold, secondsPerBin, distance) ⇒ <code>object</code>
Given a track, a selected time interval and a threshold,
this function searches for parts in the track that are
similar to the selection.
It uses a sliding window with the size of the selection
and a stride given as argument.
**Kind**: static method of [<code>comparison/Similarity</code>](#module_comparison/Similarity)
**Returns**: <code>object</code> - similar parts
| Param | Type | Description |
| --- | --- | --- |
| track | [<code>Array.<Note></code>](#Note) | array of Note objects |
| selectedInterval | <code>Array.<number></code> | [startTime, endTime] in seconds |
| stride | <code>number</code> | stride for the sliding window in number of bins |
| threshold | <code>number</code> | distance threshold below which parts are considered similar |
| secondsPerBin | <code>number</code> | time bin size in seconds |
| distance | <code>string</code> | one of: 'dtw', 'euclidean', 'nearest' |
<a name="module_comparison/Similarity.getTrackSimilarity"></a>
### comparison/Similarity.getTrackSimilarity(discrA, discrB, distance) ⇒ <code>number</code>
Uses calculates the distance between
two discretized tracks, for each pitch separately.
Pitch-wise distances are averaged and a penalty is added to the distance
for pitches that are not occuring in both tracks
**Kind**: static method of [<code>comparison/Similarity</code>](#module_comparison/Similarity)
**Returns**: <code>number</code> - distance
**See**: https://github.com/GordonLesti/dynamic-time-warping
| Param | Type | Description |
| --- | --- | --- |
| discrA | <code>Map</code> | discretized track |
| discrB | <code>Map</code> | discretized track |
| distance | <code>string</code> | one of: 'euclidean', 'nearest' |
<a name="module_comparison/Similarity.discretizeTime"></a>
### comparison/Similarity.discretizeTime(track, secondsPerBin) ⇒ <code>Map</code>
- Normalizes Note times to be between 0 and (maxTime - minTime),
- discretizes the start and end time by using Math.round to get
the closest time bin (beat) and
- Creates one array for each pitch, where each entry contains
either a 0 (no note at that time bin) or a 1 (note at that time bin)
**Kind**: static method of [<code>comparison/Similarity</code>](#module_comparison/Similarity)
**Returns**: <code>Map</code> - pitch to binArray
| Param | Type | Description |
| --- | --- | --- |
| track | [<code>Array.<Note></code>](#Note) | an array of Note objects |
| secondsPerBin | <code>number</code> | time bin size in seconds |
<a name="module_comparison/Similarity..countActiveNoteBins"></a>
### comparison/Similarity~countActiveNoteBins(binArray) ⇒ <code>number</code>
Counts the occurence of 1 in an array
**Kind**: inner method of [<code>comparison/Similarity</code>](#module_comparison/Similarity)
**Returns**: <code>number</code> - occurence of 1
| Param | Type | Description |
| --- | --- | --- |
| binArray | <code>Array.<number></code> | array |
<a name="module_comparison/Similarity..sliceDiscretizedTrack"></a>
### comparison/Similarity~sliceDiscretizedTrack(trackMap, startBin, endBin) ⇒ <code>Map</code>
Slices bins out of a discretices track.
This is done for each pitch separately
**Kind**: inner method of [<code>comparison/Similarity</code>](#module_comparison/Similarity)
**Returns**: <code>Map</code> - map with sliced arrays
| Param | Type | Description |
| --- | --- | --- |
| trackMap | <code>Map</code> | Map pitch->binArray |
| startBin | <code>number</code> | index of first bin |
| endBin | <code>number</code> | index of last bin |
<a name="module_comparison/Similarity..euclideanDistanceSquared"></a>
### comparison/Similarity~euclideanDistanceSquared(A, B) ⇒ <code>number</code>
Returns sum_{i=0}^{N-1}{(a_i-b_i)^2},
i.e. Euclidean distance but without square root
**Kind**: inner method of [<code>comparison/Similarity</code>](#module_comparison/Similarity)
**Returns**: <code>number</code> - Euclidean distance
| Param | Type | Description |
| --- | --- | --- |
| A | <code>Array.<number></code> | an array |
| B | <code>Array.<number></code> | another array |
<a name="module_comparison/Similarity..neirestNeighborDistance"></a>
### comparison/Similarity~neirestNeighborDistance(A, B) ⇒ <code>number</code>
Given two arrays containing 1s and 0s, this algorithm
goes through all bins and for each bin where one array
has a 1 and the other a 0, it searches for the closest 1
next to the 0.
The distance is then added to the global distance.
**Kind**: inner method of [<code>comparison/Similarity</code>](#module_comparison/Similarity)
**Returns**: <code>number</code> - nearest neighbor distance
| Param | Type | Description |
| --- | --- | --- |
| A | <code>Array.<number></code> | an array |
| B | <code>Array.<number></code> | another array |
<a name="module_comparison/SimilarSections"></a>
## comparison/SimilarSections
* [comparison/SimilarSections](#module_comparison/SimilarSections)
* [.findSimilarNoteSections(notes, startTime, endTime, threshold)](#module_comparison/SimilarSections.findSimilarNoteSections) ⇒ <code>Array.<object></code>
* [.findSimilarStringSections(dataString, searchString, threshold)](#module_comparison/SimilarSections.findSimilarStringSections) ⇒ <code>Array.<object></code>
<a name="module_comparison/SimilarSections.findSimilarNoteSections"></a>
### comparison/SimilarSections.findSimilarNoteSections(notes, startTime, endTime, threshold) ⇒ <code>Array.<object></code>
Turns an array of notes into a string to perform pattern matching search for similar
patterns.
**Kind**: static method of [<code>comparison/SimilarSections</code>](#module_comparison/SimilarSections)
**Returns**: <code>Array.<object></code> - {index, distance, startTime, endTime}
| Param | Type | Description |
| --- | --- | --- |
| notes | [<code>Array.<Note></code>](#Note) | notes, must be sorted by Note.start |
| startTime | <code>number</code> | start time of the section to search |
| endTime | <code>number</code> | end time for the section to search |
| threshold | <code>number</code> | threshold for normalized Levenshtein distance in [0, 1] |
<a name="module_comparison/SimilarSections.findSimilarStringSections"></a>
### comparison/SimilarSections.findSimilarStringSections(dataString, searchString, threshold) ⇒ <code>Array.<object></code>
Finds similar sections in a string via Levenshtein distance
**Kind**: static method of [<code>comparison/SimilarSections</code>](#module_comparison/SimilarSections)
**Returns**: <code>Array.<object></code> - {index, distance}
| Param | Type | Description |
| --- | --- | --- |
| dataString | <code>stringArray</code> | they string to search in |
| searchString | <code>stringArray</code> | the string to search for |
| threshold | <code>number</code> | threshold for normalized Levenshtein distance in [0, 1] |
<a name="module_instruments/StringedFingering"></a>
## instruments/StringedFingering
**Todo**
- [ ] unfinished
- [ ] not tested
* [instruments/StringedFingering](#module_instruments/StringedFingering)
* [.FretboardPosition](#module_instruments/StringedFingering.FretboardPosition)
* [new exports.FretboardPosition(string, fret)](#new_module_instruments/StringedFingering.FretboardPosition_new)
* [.moveBy(string, fret)](#module_instruments/StringedFingering.FretboardPosition+moveBy)
* [.isValid(maxString, maxFret)](#module_instruments/StringedFingering.FretboardPosition+isValid) ⇒ <code>boolean</code>
* [.equals(otherFretboardPosition)](#module_instruments/StringedFingering.FretboardPosition+equals) ⇒ <code>boolean</code>
* [.toString()](#module_instruments/StringedFingering.FretboardPosition+toString) ⇒ <code>string</code>
* [.clone()](#module_instruments/StringedFingering.FretboardPosition+clone) ⇒ <code>FretboardPosition</code>
* [.difference(otherFretboardPosition)](#module_instruments/StringedFingering.FretboardPosition+difference) ⇒ <code>object</code>
* [.HandPose](#module_instruments/StringedFingering.HandPose)
* [new exports.HandPose(fingerPositions)](#new_module_instruments/StringedFingering.HandPose_new)
* [.moveFingerTo(index, newPosition)](#module_instruments/StringedFingering.HandPose+moveFingerTo)
* [.liftFinger(index)](#module_instruments/StringedFingering.HandPose+liftFinger)
* [.moveFingerBy(index, string, fret)](#module_instruments/StringedFingering.HandPose+moveFingerBy)
* [.moveHandBy(string, fret)](#module_instruments/StringedFingering.HandPose+moveHandBy)
* [.isValid(maxString, maxFret)](#module_instruments/StringedFingering.HandPose+isValid) ⇒ <code>boolean</code>
* [.euqals(otherHandPose)](#module_instruments/StringedFingering.HandPose+euqals) ⇒ <code>boolean</code>
* [.toString()](#module_instruments/StringedFingering.HandPose+toString) ⇒ <code>string</code>
* [.clone()](#module_instruments/StringedFingering.HandPose+clone) ⇒ <code>HandPose</code>
* [.difference(otherHandPose)](#module_instruments/StringedFingering.HandPose+difference) ⇒ <code>Array.<object></code>
* [.costOfMovement(otherHandPose)](#module_instruments/StringedFingering.HandPose+costOfMovement) ⇒ <code>number</code>
<a name="module_instruments/StringedFingering.FretboardPosition"></a>
### instruments/StringedFingering.FretboardPosition
Represents a positon as {string, fret}
**Kind**: static class of [<code>instruments/StringedFingering</code>](#module_instruments/StringedFingering)
* [.FretboardPosition](#module_instruments/StringedFingering.FretboardPosition)
* [new exports.FretboardPosition(string, fret)](#new_module_instruments/StringedFingering.FretboardPosition_new)
* [.moveBy(string, fret)](#module_instruments/StringedFingering.FretboardPosition+moveBy)
* [.isValid(maxString, maxFret)](#module_instruments/StringedFingering.FretboardPosition+isValid) ⇒ <code>boolean</code>
* [.equals(otherFretboardPosition)](#module_instruments/StringedFingering.FretboardPosition+equals) ⇒ <code>boolean</code>
* [.toString()](#module_instruments/StringedFingering.FretboardPosition+toString) ⇒ <code>string</code>
* [.clone()](#module_instruments/StringedFingering.FretboardPosition+clone) ⇒ <code>FretboardPosition</code>
* [.difference(otherFretboardPosition)](#module_instruments/StringedFingering.FretboardPosition+difference) ⇒ <code>object</code>
<a name="new_module_instruments/StringedFingering.FretboardPosition_new"></a>
#### new exports.FretboardPosition(string, fret)
| Param | Type | Description |
| --- | --- | --- |
| string | <code>number</code> | string |
| fret | <code>number</code> | fret |
<a name="module_instruments/StringedFingering.FretboardPosition+moveBy"></a>
#### fretboardPosition.moveBy(string, fret)
Moves the positon by string and fret
**Kind**: instance method of [<code>FretboardPosition</code>](#module_instruments/StringedFingering.Fretboard