note-mapper 1.0.0 → 1.0.2
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 +281 -0
- package/package.json +10 -3
- /package/{index.js → src/index.js} +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# note-mapper
|
|
2
|
+
|
|
3
|
+
Maps guitar notes from [note-listener](https://www.npmjs.com/package/note-listener) to scale degrees, intervals, and game actions.
|
|
4
|
+
|
|
5
|
+
Use it to turn a guitar into a game controller — the player picks a key and scale, and their fretboard positions map to actions regardless of what key they're in.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install note-mapper
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`note-listener` should already be installed in your project as this package works alongside it.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
import { createPitchListener } from "note-listener"
|
|
23
|
+
import { createMapper, SCALES, ACTIONS_5 } from "note-mapper"
|
|
24
|
+
|
|
25
|
+
const mapper = createMapper({
|
|
26
|
+
scale: SCALES["pentatonic_minor"]["A"],
|
|
27
|
+
degreeActions: ACTIONS_5,
|
|
28
|
+
onAction(action, meta) {
|
|
29
|
+
console.log(action) // "jump", "attack" etc
|
|
30
|
+
console.log(meta) // { type, note, freq, degree, cents }
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const listener = await createPitchListener({
|
|
35
|
+
onNotes(notes) {
|
|
36
|
+
mapper.process(notes)
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
listener.start()
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Concepts
|
|
46
|
+
|
|
47
|
+
### Scale degrees
|
|
48
|
+
|
|
49
|
+
A scale degree is the position of a note within a scale — 0 is always the root.
|
|
50
|
+
The player can switch key and the same fret positions produce the same actions.
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
A minor pentatonic: ["A", "C", "D", "E", "G"]
|
|
54
|
+
0 1 2 3 4
|
|
55
|
+
|
|
56
|
+
Play "A" → degree 0 → "jump"
|
|
57
|
+
Play "E" → degree 3 → "attack"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Intervals
|
|
61
|
+
|
|
62
|
+
An interval is the distance in semitones between two notes played together.
|
|
63
|
+
Used for two-note combinations like power chords triggering special moves.
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Play A + E together → Perfect 5th (7 semitones) → "power_attack"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## API
|
|
72
|
+
|
|
73
|
+
### `createMapper(options)`
|
|
74
|
+
|
|
75
|
+
Creates a mapper instance. Call `mapper.process(notes)` inside `onNotes`.
|
|
76
|
+
|
|
77
|
+
| Option | Type | Default | Description |
|
|
78
|
+
|---|---|---|---|
|
|
79
|
+
| `scale` | `string[]` | required | Scale array from `SCALES` |
|
|
80
|
+
| `degreeActions` | `object` | `ACTIONS_7` | Maps degree → action string |
|
|
81
|
+
| `intervalActions` | `object` | `ACTIONS_INTERVAL` | Maps semitones → action string |
|
|
82
|
+
| `centsTolerance` | `number` | `40` | Cents off-pitch still accepted |
|
|
83
|
+
| `intervalWindow` | `number` | `150` | Ms window for interval detection |
|
|
84
|
+
| `onAction` | `function` | required | Fires when an action is detected |
|
|
85
|
+
|
|
86
|
+
#### Returns
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
{
|
|
90
|
+
process(notes), // call this inside onNotes every frame
|
|
91
|
+
setScale(newScale), // swap scale at runtime
|
|
92
|
+
setDegreeActions(map), // swap degree actions at runtime
|
|
93
|
+
setIntervalActions(map), // swap interval actions at runtime
|
|
94
|
+
getHeldNotes(), // returns currently held notes
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### `SCALES`
|
|
101
|
+
|
|
102
|
+
All scales, keyed by type then root note.
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
import { SCALES } from "note-mapper"
|
|
106
|
+
|
|
107
|
+
SCALES["major"]["G"] // G major
|
|
108
|
+
SCALES["pentatonic_minor"]["E"] // E minor pentatonic
|
|
109
|
+
SCALES["dorian"]["A"] // A dorian
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Available scale types:**
|
|
113
|
+
|
|
114
|
+
| Key | Name | Notes |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| `major` | Major / Ionian | 7 |
|
|
117
|
+
| `natural_minor` | Natural Minor / Aeolian | 7 |
|
|
118
|
+
| `pentatonic_minor` | Minor Pentatonic | 5 |
|
|
119
|
+
| `pentatonic_major` | Major Pentatonic | 5 |
|
|
120
|
+
| `blues` | Blues | 6 |
|
|
121
|
+
| `dorian` | Dorian | 7 |
|
|
122
|
+
| `phrygian` | Phrygian | 7 |
|
|
123
|
+
| `lydian` | Lydian | 7 |
|
|
124
|
+
| `mixolydian` | Mixolydian | 7 |
|
|
125
|
+
| `locrian` | Locrian | 7 |
|
|
126
|
+
| `harmonic_minor` | Harmonic Minor | 7 |
|
|
127
|
+
| `melodic_minor` | Melodic Minor | 7 |
|
|
128
|
+
| `phrygian_dominant` | Phrygian Dominant | 7 |
|
|
129
|
+
| `whole_tone` | Whole Tone | 6 |
|
|
130
|
+
| `diminished` | Diminished | 8 |
|
|
131
|
+
|
|
132
|
+
All scale types are available in all 12 keys: `C C# D Eb E F F# G Ab A Bb B`
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
### `KEYS`
|
|
137
|
+
|
|
138
|
+
Array of all 12 root keys — useful for building a key selector UI.
|
|
139
|
+
|
|
140
|
+
```js
|
|
141
|
+
import { KEYS } from "note-mapper"
|
|
142
|
+
// ["C", "C#", "D", "Eb", "E", "F", "F#", "G", "Ab", "A", "Bb", "B"]
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
### Default action maps
|
|
148
|
+
|
|
149
|
+
```js
|
|
150
|
+
import { ACTIONS_5, ACTIONS_6, ACTIONS_7, ACTIONS_INTERVAL } from "note-mapper"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**`ACTIONS_5`** — for pentatonic scales (5 notes)
|
|
154
|
+
|
|
155
|
+
| Degree | Action |
|
|
156
|
+
|---|---|
|
|
157
|
+
| 0 | jump |
|
|
158
|
+
| 1 | move_left |
|
|
159
|
+
| 2 | move_right |
|
|
160
|
+
| 3 | attack |
|
|
161
|
+
| 4 | shield |
|
|
162
|
+
|
|
163
|
+
**`ACTIONS_6`** — for blues scale (6 notes)
|
|
164
|
+
|
|
165
|
+
Adds `special` at degree 5.
|
|
166
|
+
|
|
167
|
+
**`ACTIONS_7`** — for diatonic scales (7 notes)
|
|
168
|
+
|
|
169
|
+
Adds `special` at degree 5 and `ultimate` at degree 6.
|
|
170
|
+
|
|
171
|
+
**`ACTIONS_INTERVAL`** — for two-note combinations
|
|
172
|
+
|
|
173
|
+
| Semitones | Interval | Action |
|
|
174
|
+
|---|---|---|
|
|
175
|
+
| 5 | Perfect 4th | special |
|
|
176
|
+
| 7 | Perfect 5th | power_attack |
|
|
177
|
+
| 3 | Minor 3rd | block |
|
|
178
|
+
| 4 | Major 3rd | dodge |
|
|
179
|
+
| 6 | Tritone | taunt |
|
|
180
|
+
| 9 | Major 6th | heal |
|
|
181
|
+
| 10 | Minor 7th | roll |
|
|
182
|
+
| 12 | Octave | ultimate |
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
### Lower level utilities
|
|
187
|
+
|
|
188
|
+
If you want more control than `createMapper` gives you, use these directly.
|
|
189
|
+
|
|
190
|
+
```js
|
|
191
|
+
import {
|
|
192
|
+
getDegree,
|
|
193
|
+
getDegreeWithTolerance,
|
|
194
|
+
degreeToNote,
|
|
195
|
+
isInScale,
|
|
196
|
+
getInterval,
|
|
197
|
+
getIntervalInfo,
|
|
198
|
+
detectInterval,
|
|
199
|
+
isInterval,
|
|
200
|
+
} from "note-mapper"
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**`getDegree(note, scale)`** — returns 0-based degree or null if not in scale
|
|
204
|
+
|
|
205
|
+
```js
|
|
206
|
+
getDegree("A2", ["A","C","D","E","G"]) // → 0
|
|
207
|
+
getDegree("F2", ["A","C","D","E","G"]) // → null
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**`getDegreeWithTolerance(note, freq, scale, centsTolerance?)`** — same but accepts slightly out of tune notes
|
|
211
|
+
|
|
212
|
+
**`degreeToNote(degree, scale)`** — reverse lookup, degree → note name
|
|
213
|
+
|
|
214
|
+
```js
|
|
215
|
+
degreeToNote(3, ["A","C","D","E","G"]) // → "E"
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**`isInScale(note, scale)`** — returns boolean
|
|
219
|
+
|
|
220
|
+
**`getInterval(freqA, freqB)`** — returns semitone count 0–12
|
|
221
|
+
|
|
222
|
+
```js
|
|
223
|
+
getInterval(440, 660) // → 7 (perfect 5th)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**`getIntervalInfo(freqA, freqB)`** — returns full interval object
|
|
227
|
+
|
|
228
|
+
```js
|
|
229
|
+
getIntervalInfo(440, 660)
|
|
230
|
+
// → { semitones: 7, name: "Perfect 5th", short: "P5", character: "power chord, strong" }
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**`detectInterval(notes, history, windowMs?)`** — detects interval from onNotes array with timing window
|
|
234
|
+
|
|
235
|
+
**`isInterval(semitones, short)`** — readable interval check
|
|
236
|
+
|
|
237
|
+
```js
|
|
238
|
+
isInterval(7, "P5") // → true
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Custom action maps
|
|
244
|
+
|
|
245
|
+
You can define your own action maps and swap them at runtime:
|
|
246
|
+
|
|
247
|
+
```js
|
|
248
|
+
const myActions = {
|
|
249
|
+
0: "fly",
|
|
250
|
+
1: "run_left",
|
|
251
|
+
2: "run_right",
|
|
252
|
+
3: "fireball",
|
|
253
|
+
4: "teleport",
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
mapper.setDegreeActions(myActions)
|
|
257
|
+
|
|
258
|
+
// swap back later
|
|
259
|
+
mapper.setDegreeActions(ACTIONS_5)
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Switching scale at runtime
|
|
265
|
+
|
|
266
|
+
```js
|
|
267
|
+
// player changes key in settings
|
|
268
|
+
mapper.setScale(SCALES["major"]["G"])
|
|
269
|
+
|
|
270
|
+
// player changes scale type
|
|
271
|
+
mapper.setScale(SCALES["dorian"]["A"])
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Held notes and interval history are cleared automatically on scale change.
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## License
|
|
279
|
+
|
|
280
|
+
MIT © Donald Edwin
|
|
281
|
+
|
package/package.json
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "note-mapper",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Map guitar notes from note-listener to scale degrees, intervals and game actions",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"exports": {
|
|
7
|
-
|
|
7
|
+
".": "./src/index.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
11
|
},
|
|
12
|
-
"keywords": [
|
|
12
|
+
"keywords": [
|
|
13
|
+
"guitar",
|
|
14
|
+
"music",
|
|
15
|
+
"pitch",
|
|
16
|
+
"scale",
|
|
17
|
+
"interval",
|
|
18
|
+
"game-controller"
|
|
19
|
+
],
|
|
13
20
|
"author": "Donald Edwin",
|
|
14
21
|
"license": "MIT",
|
|
15
22
|
"type": "module",
|
|
File without changes
|