@greenblacksky/honmoon 0.0.0-stage → 0.4.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/LICENSE +21 -0
- package/README.md +81 -2
- package/package.json +58 -4
- package/src/lib/audio/context.ts +29 -0
- package/src/lib/audio/metronome.svelte.ts +146 -0
- package/src/lib/audio/mic.ts +254 -0
- package/src/lib/audio/pitch.ts +133 -0
- package/src/lib/audio/rhythmplay.ts +152 -0
- package/src/lib/audio/synth.ts +409 -0
- package/src/lib/audio/voiceplay.ts +60 -0
- package/src/lib/drills/defs.ts +459 -0
- package/src/lib/drills/questions.ts +920 -0
- package/src/lib/drills/registry.svelte.ts +167 -0
- package/src/lib/drills/runtime.svelte.ts +629 -0
- package/src/lib/drills/verdict.ts +241 -0
- package/src/lib/index.ts +117 -0
- package/src/lib/learn/describe.ts +72 -0
- package/src/lib/learn/pools.ts +44 -0
- package/src/lib/learn/progress.ts +100 -0
- package/src/lib/learn/session.ts +304 -0
- package/src/lib/music/bass.ts +139 -0
- package/src/lib/music/clefs.ts +218 -0
- package/src/lib/music/intervals.ts +94 -0
- package/src/lib/music/notes.ts +133 -0
- package/src/lib/music/rhythm.ts +624 -0
- package/src/lib/music/scales.ts +560 -0
- package/src/lib/music/voice.ts +227 -0
- package/src/lib/music/warmups.ts +318 -0
- package/src/lib/nav.svelte.ts +53 -0
- package/src/lib/notation/fretboard.ts +187 -0
- package/src/lib/notation/glyphdata.ts +101 -0
- package/src/lib/notation/glyphs.ts +71 -0
- package/src/lib/notation/icons.ts +12 -0
- package/src/lib/notation/keyboard.ts +166 -0
- package/src/lib/notation/rhythmsvg.ts +341 -0
- package/src/lib/notation/staff.ts +288 -0
- package/src/lib/notation/svg.ts +37 -0
- package/src/lib/notation/tab.ts +80 -0
- package/src/lib/store/honmoon.svelte.ts +329 -0
- package/src/lib/store/normalize.ts +23 -0
- package/src/lib/store/sync.ts +43 -0
- package/src/lib/store/types.ts +101 -0
- package/src/lib/styles/honmoon.css +2064 -0
- package/src/lib/ui/AccRow.svelte +23 -0
- package/src/lib/ui/BackBar.svelte +23 -0
- package/src/lib/ui/BassRow.svelte +30 -0
- package/src/lib/ui/Chips.svelte +23 -0
- package/src/lib/ui/DataCard.svelte +66 -0
- package/src/lib/ui/Fretboard.svelte +71 -0
- package/src/lib/ui/Keyboard.svelte +54 -0
- package/src/lib/ui/MetronomePanel.svelte +101 -0
- package/src/lib/ui/RefBar.svelte +28 -0
- package/src/lib/ui/RhythmBar.svelte +9 -0
- package/src/lib/ui/Shell.svelte +96 -0
- package/src/lib/ui/StaffRun.svelte +46 -0
- package/src/lib/ui/Stat.svelte +13 -0
- package/src/lib/ui/actions.ts +36 -0
- package/src/lib/ui/keyfollow.svelte.ts +48 -0
- package/src/lib/ui/overlay.ts +15 -0
- package/src/lib/ui/refdata.ts +355 -0
- package/src/lib/ui/scaleboard.ts +420 -0
- package/src/lib/ui/screens/DegreesRef.svelte +405 -0
- package/src/lib/ui/screens/DrillScreen.svelte +1155 -0
- package/src/lib/ui/screens/Explorer.svelte +245 -0
- package/src/lib/ui/screens/FamilyScreen.svelte +280 -0
- package/src/lib/ui/screens/Glossary.svelte +65 -0
- package/src/lib/ui/screens/IntervalRef.svelte +37 -0
- package/src/lib/ui/screens/LearnIndex.svelte +44 -0
- package/src/lib/ui/screens/MetronomeScreen.svelte +17 -0
- package/src/lib/ui/screens/PracticeHome.svelte +159 -0
- package/src/lib/ui/screens/RhythmRef.svelte +239 -0
- package/src/lib/ui/screens/ScalesScreen.svelte +210 -0
- package/src/lib/ui/screens/SessionDone.svelte +119 -0
- package/src/lib/ui/screens/SetupScreen.svelte +548 -0
- package/src/lib/ui/screens/StaffMap.svelte +230 -0
- package/src/lib/ui/screens/StatsScreen.svelte +478 -0
- package/src/lib/ui/screens/TapCalibration.svelte +186 -0
- package/src/lib/ui/tapfix.ts +93 -0
- package/src/lib/ui/types.ts +40 -0
- package/src/lib/util/list.ts +4 -0
- package/src/lib/util/random.ts +23 -0
- package/src/lib/util/text.ts +50 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Reading scale degrees, in five short pages rather than one long one, because
|
|
3
|
+
each builds on the one before and a phone screen holds about one idea at a
|
|
4
|
+
time: what a degree is, what a flat or sharp in front of one means, reading
|
|
5
|
+
a whole scale as a formula, where every degree sits under the hand, and a
|
|
6
|
+
few to try. Every note name shown is spelled by scaleNotes(), the same code
|
|
7
|
+
the drills use, so nothing here can disagree with what a drill marks right.
|
|
8
|
+
-->
|
|
9
|
+
<script lang="ts" module>
|
|
10
|
+
/** The page you are on, the scale picked for the map and the fret its root sits on. */
|
|
11
|
+
const DEGT = $state({ tab: 0, sid: 'major', rootF: 3 });
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
import { honmoon } from '../../store/honmoon.svelte';
|
|
16
|
+
import { mdoOn, noteName, pcOf } from '../../music/notes';
|
|
17
|
+
import { degPretty, scaleDef } from '../../music/scales';
|
|
18
|
+
import { degStaffSVG } from '../../notation/staff';
|
|
19
|
+
import { go, hasRoute, scrollToTop } from '../../nav.svelte';
|
|
20
|
+
import { degKeyTable, degMapSVG, degRuler, degThirdsSVG, degWorked } from '../scaleboard';
|
|
21
|
+
import { DEGQ, DEGTABS } from '../refdata';
|
|
22
|
+
import Keyboard from '../Keyboard.svelte';
|
|
23
|
+
|
|
24
|
+
const { back }: { back?: { label: string; to: string } } = $props();
|
|
25
|
+
const page = $derived(Math.max(0, Math.min(DEGTABS.length - 1, DEGT.tab)));
|
|
26
|
+
const pref = $derived(honmoon.settings.pref);
|
|
27
|
+
function showPage(i: number) {
|
|
28
|
+
DEGT.tab = i;
|
|
29
|
+
scrollToTop();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Frets the degree map's root can sit on, and the open E string they count from. */
|
|
33
|
+
const ROOT_FRETS = [1, 3, 5, 7];
|
|
34
|
+
const LOW_E = 40;
|
|
35
|
+
const ROWS: [string, string][] = [
|
|
36
|
+
['major', 'The ruler itself.'],
|
|
37
|
+
['natmin', 'Major with ♭3, ♭6, ♭7.'],
|
|
38
|
+
['dorian', 'Minor, but with a plain 6. Brighter, funkier.'],
|
|
39
|
+
['mixo', 'Major with a ♭7. Bluesy, dominant.'],
|
|
40
|
+
['minpent', 'Minor with the 2 and ♭6 left out — five notes, no half steps.'],
|
|
41
|
+
['majpent', 'Major with the 4 and 7 left out.'],
|
|
42
|
+
['blues', 'Minor pentatonic plus the ♭5.'],
|
|
43
|
+
];
|
|
44
|
+
const PICKS: [string, string][] = [
|
|
45
|
+
['all', 'Every degree'],
|
|
46
|
+
['major', 'Major'],
|
|
47
|
+
['natmin', 'Natural minor'],
|
|
48
|
+
['minpent', 'Minor pent.'],
|
|
49
|
+
['majpent', 'Major pent.'],
|
|
50
|
+
['blues', 'Blues'],
|
|
51
|
+
['dorian', 'Dorian'],
|
|
52
|
+
['mixo', 'Mixolydian'],
|
|
53
|
+
];
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
<div class="bar">
|
|
57
|
+
<button class="ghost" id="backlearn" onclick={() => go(back?.to ?? 'learn')}
|
|
58
|
+
>← {back?.label ?? 'Learn'}</button
|
|
59
|
+
><span class="spacer"></span><span class="tick"
|
|
60
|
+
>Scale degrees · {page + 1} / {DEGTABS.length}</span
|
|
61
|
+
>
|
|
62
|
+
</div>
|
|
63
|
+
<div class="sec">
|
|
64
|
+
<div class="levels dtabs">
|
|
65
|
+
{#each DEGTABS as title, i (i)}<button
|
|
66
|
+
class="chip sm"
|
|
67
|
+
data-degtab={i}
|
|
68
|
+
aria-pressed={i === page}
|
|
69
|
+
onclick={() => showPage(i)}>{i + 1} · {title}</button
|
|
70
|
+
>{/each}
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
{#if page === 0}
|
|
75
|
+
<div class="sec">
|
|
76
|
+
<h2>A number instead of a letter</h2>
|
|
77
|
+
<div class="card stack">
|
|
78
|
+
<p class="note">
|
|
79
|
+
A <b>degree</b> is a note’s place in the scale, counting the root as <b>1</b>. In C major, C
|
|
80
|
+
is 1, D is 2, E is 3, and so on up to B, which is 7. The next C is the octave: 8, or 1
|
|
81
|
+
again.
|
|
82
|
+
</p>
|
|
83
|
+
{@html degStaffSVG('major', 0, 48)}
|
|
84
|
+
<p class="note">
|
|
85
|
+
Letters on the top row, degrees underneath. The letter tells you <i>which</i> note; the
|
|
86
|
+
degree tells you <i>what job</i> it is doing in this key.
|
|
87
|
+
</p>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
<div class="sec">
|
|
91
|
+
<h2>Same numbers, any key</h2>
|
|
92
|
+
<div class="card stack">
|
|
93
|
+
{@html degStaffSVG('major', 7, 43, [7])}
|
|
94
|
+
<p class="note">
|
|
95
|
+
G major. The letters have all changed, but the numbers are the same, and so is the sound of
|
|
96
|
+
each one. The <b>5</b> — marked — was G in C major and is D here, and in both keys it is the note
|
|
97
|
+
that sounds strong and stable, just short of home.
|
|
98
|
+
</p>
|
|
99
|
+
{@html degKeyTable('major', [0, 7, 5, 2], [7])}
|
|
100
|
+
<p class="note">
|
|
101
|
+
This is the whole reason for degrees. Learn that a line goes <b>1 – 5 – 8</b> and you can
|
|
102
|
+
play it in any key without learning it again. Learn that it goes <i>C – G – C</i> and you know
|
|
103
|
+
it in one.
|
|
104
|
+
</p>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
<div class="sec">
|
|
108
|
+
<h2>Major is the ruler</h2>
|
|
109
|
+
<div class="card stack">
|
|
110
|
+
<p class="note">
|
|
111
|
+
An octave is twelve frets. Here they are in a row, counted up from the root:
|
|
112
|
+
</p>
|
|
113
|
+
{@html degRuler(null, { frets: true })}
|
|
114
|
+
<p class="note">
|
|
115
|
+
The seven <b>bold</b> slots are the major scale — that is what the plain numbers
|
|
116
|
+
<i>mean</i>. The five faint slots in between have no plain number of their own, so they are
|
|
117
|
+
named after a neighbour with a ♭ or ♯ in front. That is the next page.
|
|
118
|
+
</p>
|
|
119
|
+
<p class="note">
|
|
120
|
+
The small numbers underneath are frets from the root, which on bass is the same as
|
|
121
|
+
semitones. 3 is four frets up, 5 is seven, and they always will be.
|
|
122
|
+
</p>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
<div class="sec">
|
|
126
|
+
<h2>Where the half steps are</h2>
|
|
127
|
+
<div class="card stack">
|
|
128
|
+
<p class="note">
|
|
129
|
+
A bass hides this. Every fret looks like every other fret, so a half step and a whole step
|
|
130
|
+
are the same picture. A keyboard draws it: the half steps are the two places where white
|
|
131
|
+
keys touch with no black key between them.
|
|
132
|
+
</p>
|
|
133
|
+
<Keyboard
|
|
134
|
+
lo={48}
|
|
135
|
+
oct={1}
|
|
136
|
+
tap="play"
|
|
137
|
+
cells={[
|
|
138
|
+
{ pc: 4, fill: 'var(--good)', label: 'E' },
|
|
139
|
+
{ pc: 5, fill: 'var(--good)', label: 'F' },
|
|
140
|
+
{ pc: 11, fill: 'var(--good)', label: 'B' },
|
|
141
|
+
{ pc: 0, fill: 'var(--good)', label: 'C' },
|
|
142
|
+
]}
|
|
143
|
+
/>
|
|
144
|
+
<p class="note">
|
|
145
|
+
E to F, and B to C. Everywhere else a black key sits in the gap and the step is a whole one.
|
|
146
|
+
Play the white keys from C to C and you have played a major scale — the famous <b
|
|
147
|
+
>whole whole half whole whole whole half</b
|
|
148
|
+
> is just this picture read left to right. Tap the keys to hear it.
|
|
149
|
+
</p>
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
{:else if page === 1}
|
|
153
|
+
<div class="sec">
|
|
154
|
+
<h2>A ♭ means one fret lower</h2>
|
|
155
|
+
<div class="card stack">
|
|
156
|
+
<p class="note">
|
|
157
|
+
A flat in front of a degree means <b>one fret lower than the major scale would put it</b>. A
|
|
158
|
+
sharp means one fret higher. That is all.
|
|
159
|
+
</p>
|
|
160
|
+
<div class="fbwrap fit">{@html degThirdsSVG()}</div>
|
|
161
|
+
<p class="note">
|
|
162
|
+
Root on the E string, fret 5 — that is A. Four frets up is the <b>3</b>, C♯. One fret below
|
|
163
|
+
it is the <b>♭3</b>, C. That single fret is the entire difference between an A major chord
|
|
164
|
+
and an A minor one.
|
|
165
|
+
</p>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
<div class="sec">
|
|
169
|
+
<h2>♭3 is not “a flat note”</h2>
|
|
170
|
+
<div class="card stack">
|
|
171
|
+
<p class="note">
|
|
172
|
+
This is the part that trips everybody. The ♭ in a degree compares it with <i>major</i>. It
|
|
173
|
+
says nothing about whether the note has a flat in its name.
|
|
174
|
+
</p>
|
|
175
|
+
{@html degStaffSVG('natmin', 4, 40, [3, 8, 10])}
|
|
176
|
+
<p class="note">
|
|
177
|
+
E natural minor. Its formula has three flat degrees — ♭3, ♭6, ♭7 — and they are G, C and D.
|
|
178
|
+
Not a flat sign among them. They are flat <i>degrees</i> because E major has G♯, C♯ and D♯ in
|
|
179
|
+
those places, and minor lowers each by a fret.
|
|
180
|
+
</p>
|
|
181
|
+
{@html degStaffSVG('major', 5, 41, [5])}
|
|
182
|
+
<p class="note">
|
|
183
|
+
And the reverse: F major. B♭ has a flat in its name, but it is just the <b>4</b> — a plain degree
|
|
184
|
+
— because it is exactly where the major scale puts the fourth note in the key of F.
|
|
185
|
+
</p>
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
<div class="sec">
|
|
189
|
+
<h2>The five in-between degrees</h2>
|
|
190
|
+
<div class="card stack">
|
|
191
|
+
{@html degRuler(null, { mark: [1, 3, 6, 8, 10] })}
|
|
192
|
+
<div class="gterm">
|
|
193
|
+
<b>♭2</b>
|
|
194
|
+
<p>
|
|
195
|
+
A fret above the root. Tense and exotic — the sound of Phrygian, flamenco and a lot of
|
|
196
|
+
metal.
|
|
197
|
+
</p>
|
|
198
|
+
</div>
|
|
199
|
+
<div class="gterm">
|
|
200
|
+
<b>♭3</b>
|
|
201
|
+
<p>The minor third. Swap the 3 for this and major becomes minor.</p>
|
|
202
|
+
</div>
|
|
203
|
+
<div class="gterm">
|
|
204
|
+
<b>♯4 / ♭5</b>
|
|
205
|
+
<p>
|
|
206
|
+
Exactly half an octave: the tritone. Called ♭5 in the blues scale, where it is the “blue
|
|
207
|
+
note”; ♯4 in Lydian, where it makes major sound like it is floating.
|
|
208
|
+
</p>
|
|
209
|
+
</div>
|
|
210
|
+
<div class="gterm">
|
|
211
|
+
<b>♭6</b>
|
|
212
|
+
<p>The darker sixth of natural minor.</p>
|
|
213
|
+
</div>
|
|
214
|
+
<div class="gterm">
|
|
215
|
+
<b>♭7</b>
|
|
216
|
+
<p>
|
|
217
|
+
A whole step below the octave instead of a half. The sound of blues, rock and funk, and of
|
|
218
|
+
every dominant 7 chord.
|
|
219
|
+
</p>
|
|
220
|
+
</div>
|
|
221
|
+
<p class="note">
|
|
222
|
+
Why one slot has two names: it is a fret above 4 and a fret below 5, and a scale names it
|
|
223
|
+
after the neighbour it is standing in for. Lydian <i>replaces</i> the 4 with it, so there it is
|
|
224
|
+
♯4. The blues scale keeps the 4 and adds this note on the way up to the 5, so there it is ♭5.
|
|
225
|
+
</p>
|
|
226
|
+
</div>
|
|
227
|
+
</div>
|
|
228
|
+
{:else if page === 2}
|
|
229
|
+
<div class="sec">
|
|
230
|
+
<h2>A scale written as degrees</h2>
|
|
231
|
+
<div class="card stack">
|
|
232
|
+
<p class="note">
|
|
233
|
+
A <b>formula</b> lists a scale’s notes as degrees instead of letters, which makes it true in every
|
|
234
|
+
key. Read it against the ruler: plain numbers are where major has them, a ♭ is a fret lower.
|
|
235
|
+
</p>
|
|
236
|
+
<div class="dform"><b>Natural minor</b><span>1 2 ♭3 4 5 ♭6 ♭7</span></div>
|
|
237
|
+
<p class="note">
|
|
238
|
+
Read aloud: <i>start from major, lower the third, sixth and seventh by a fret.</i> That is how
|
|
239
|
+
you build it in any key without memorising the letters.
|
|
240
|
+
</p>
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
<div class="sec">
|
|
244
|
+
<h2>Worked through: A minor</h2>
|
|
245
|
+
<div class="card stack">
|
|
246
|
+
<p class="note">
|
|
247
|
+
Write out A major, then apply the three flats. The notes that moved are marked.
|
|
248
|
+
</p>
|
|
249
|
+
{@html degWorked('major', 'natmin', 9)}
|
|
250
|
+
<p class="note">
|
|
251
|
+
C♯ down to C, F♯ to F, G♯ to G. What is left is A B C D E F G — no sharps or flats at all,
|
|
252
|
+
which is why A minor is the first minor key anyone learns.
|
|
253
|
+
</p>
|
|
254
|
+
</div>
|
|
255
|
+
</div>
|
|
256
|
+
<div class="sec">
|
|
257
|
+
<h2>Side by side</h2>
|
|
258
|
+
<div class="card stack">
|
|
259
|
+
<p class="note">
|
|
260
|
+
Each row is one scale laid over the ruler. The column tells you the fret; the label is what
|
|
261
|
+
that scale calls it. Compare any two rows and the difference is a handful of cells — which
|
|
262
|
+
is exactly how musicians describe them.
|
|
263
|
+
</p>
|
|
264
|
+
{#each ROWS as [sid, blurb] (sid)}
|
|
265
|
+
<div class="drow">
|
|
266
|
+
<div class="drn"><b>{scaleDef(sid).n}</b><span>{blurb}</span></div>
|
|
267
|
+
{@html degRuler(sid, { compact: true })}
|
|
268
|
+
</div>
|
|
269
|
+
{/each}
|
|
270
|
+
<p class="note">
|
|
271
|
+
Dorian against natural minor: one cell, the 6. Mixolydian against major: one cell, the 7.
|
|
272
|
+
Most of what makes a scale sound the way it does is one or two degrees.
|
|
273
|
+
</p>
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
{:else if page === 3}
|
|
277
|
+
{@const pickedSid = DEGT.sid}
|
|
278
|
+
<div class="sec">
|
|
279
|
+
<h2>Every degree, under one hand</h2>
|
|
280
|
+
<div class="card stack">
|
|
281
|
+
<p class="note">
|
|
282
|
+
With the root on the E string, every degree has a fixed spot within reach. Pick a scale to
|
|
283
|
+
see which of them it uses.
|
|
284
|
+
</p>
|
|
285
|
+
<div class="levels">
|
|
286
|
+
{#each PICKS as [sid, title] (sid)}<button
|
|
287
|
+
class="chip sm"
|
|
288
|
+
data-degsid={sid}
|
|
289
|
+
aria-pressed={pickedSid === sid}
|
|
290
|
+
onclick={() => {
|
|
291
|
+
DEGT.sid = sid;
|
|
292
|
+
}}>{title}</button
|
|
293
|
+
>{/each}
|
|
294
|
+
</div>
|
|
295
|
+
<div class="fbwrap fit">
|
|
296
|
+
{@html degMapSVG(pickedSid === 'all' ? null : pickedSid, DEGT.rootF)}
|
|
297
|
+
</div>
|
|
298
|
+
<div class="legend">
|
|
299
|
+
<span><b style="background:var(--accent);border-radius:50%"></b>root</span>
|
|
300
|
+
<span
|
|
301
|
+
><b style="background:var(--dot);border:1px solid var(--line-2);border-radius:50%"
|
|
302
|
+
></b>plain degree</span
|
|
303
|
+
>
|
|
304
|
+
<span><b style="background:var(--good);border-radius:50%"></b>♭ or ♯ degree</span>
|
|
305
|
+
{#if pickedSid !== 'all'}<span
|
|
306
|
+
><b style="border:1.4px solid var(--ink-3);border-radius:50%"></b>not in this scale</span
|
|
307
|
+
>{/if}
|
|
308
|
+
</div>
|
|
309
|
+
<p class="note">
|
|
310
|
+
{#if pickedSid === 'all'}All twelve, plus the octave. The 3 and the 6 sit a fret <i
|
|
311
|
+
>behind</i
|
|
312
|
+
> the root on the next string up — that is why a major shape reaches back.{:else}{scaleDef(
|
|
313
|
+
pickedSid,
|
|
314
|
+
).n}: {scaleDef(pickedSid).dg.map(degPretty).join(' ')}. Filled spots are the scale; rings
|
|
315
|
+
are the degrees it leaves out.{/if}
|
|
316
|
+
</p>
|
|
317
|
+
</div>
|
|
318
|
+
</div>
|
|
319
|
+
<div class="sec">
|
|
320
|
+
<h2>Move the 1, keep the shape</h2>
|
|
321
|
+
<div class="card stack">
|
|
322
|
+
<p class="note">
|
|
323
|
+
The map above has its root on fret {DEGT.rootF}, which makes it {noteName(
|
|
324
|
+
pcOf(40 + DEGT.rootF),
|
|
325
|
+
'en',
|
|
326
|
+
pref,
|
|
327
|
+
)}. Move the root and every degree comes with it, still in the same place relative to it.
|
|
328
|
+
<b>That is changing key on the bass.</b> A piano player relearns the pattern for every key; you
|
|
329
|
+
move your hand.
|
|
330
|
+
</p>
|
|
331
|
+
<div class="bar">
|
|
332
|
+
<span class="hint">Root at fret</span>
|
|
333
|
+
{#each ROOT_FRETS as fret (fret)}<button
|
|
334
|
+
class="chip sm"
|
|
335
|
+
data-degroot={fret}
|
|
336
|
+
aria-pressed={DEGT.rootF === fret}
|
|
337
|
+
onclick={() => {
|
|
338
|
+
DEGT.rootF = fret;
|
|
339
|
+
}}>{fret} · {noteName(pcOf(LOW_E + fret), 'en', pref)}</button
|
|
340
|
+
>{/each}
|
|
341
|
+
</div>
|
|
342
|
+
<p class="note">
|
|
343
|
+
Try it with the map above: the dots move, their shape does not. With the root on the A
|
|
344
|
+
string instead, it all works the same way, one string higher.
|
|
345
|
+
</p>
|
|
346
|
+
</div>
|
|
347
|
+
</div>
|
|
348
|
+
{:else}
|
|
349
|
+
<div class="sec">
|
|
350
|
+
<h2>Try a few</h2>
|
|
351
|
+
<div class="card stack">
|
|
352
|
+
<p class="note">Work each one out, then tap to check. None of these are scored.</p>
|
|
353
|
+
{#each DEGQ as [question, answer, why], i (i)}
|
|
354
|
+
<details class="dq">
|
|
355
|
+
<summary>{@html question}</summary>
|
|
356
|
+
<div>
|
|
357
|
+
<b>{answer}</b>
|
|
358
|
+
<p>{why}</p>
|
|
359
|
+
</div>
|
|
360
|
+
</details>
|
|
361
|
+
{/each}
|
|
362
|
+
</div>
|
|
363
|
+
</div>
|
|
364
|
+
<div class="sec">
|
|
365
|
+
<h2>Where to go next</h2>
|
|
366
|
+
<div class="card stack">
|
|
367
|
+
<p class="note">
|
|
368
|
+
<b>Scale explorer</b> shows any scale in any key with its degrees written under every note — the
|
|
369
|
+
quickest way to check a formula you have worked out.
|
|
370
|
+
</p>
|
|
371
|
+
<p class="note">
|
|
372
|
+
<b>Degree drills</b> — name the degree of a note, find a degree on the neck, sing one — are
|
|
373
|
+
in <i>Names & keys</i> here, and in Mira (bass) and Rumi (voice). {mdoOn()
|
|
374
|
+
? 'They are switched on.'
|
|
375
|
+
: 'They are switched off until you turn on movable do in Setup, because degrees and movable do are the same idea.'}
|
|
376
|
+
</p>
|
|
377
|
+
<div class="bar">
|
|
378
|
+
{#if hasRoute('sx')}<button class="ghost" data-go="sx" onclick={() => go('sx')}
|
|
379
|
+
>Scale explorer</button
|
|
380
|
+
>{/if}<span class="spacer"></span>
|
|
381
|
+
{#if !mdoOn() && hasRoute('setup')}<button
|
|
382
|
+
class="ghost"
|
|
383
|
+
data-go="setup"
|
|
384
|
+
onclick={() => go('setup')}>Setup</button
|
|
385
|
+
>{/if}
|
|
386
|
+
</div>
|
|
387
|
+
</div>
|
|
388
|
+
</div>
|
|
389
|
+
{/if}
|
|
390
|
+
|
|
391
|
+
<div class="sec">
|
|
392
|
+
<div class="bar">
|
|
393
|
+
{#if page > 0}<button class="ghost" data-degtab={page - 1} onclick={() => showPage(page - 1)}
|
|
394
|
+
>← {DEGTABS[page - 1]}</button
|
|
395
|
+
>{/if}
|
|
396
|
+
<span class="spacer"></span>
|
|
397
|
+
{#if page < DEGTABS.length - 1}<button
|
|
398
|
+
class="ghost on"
|
|
399
|
+
data-degtab={page + 1}
|
|
400
|
+
onclick={() => showPage(page + 1)}>{DEGTABS[page + 1]} →</button
|
|
401
|
+
>
|
|
402
|
+
{:else}<button class="ghost" id="backlearn" onclick={() => go(back?.to ?? 'learn')}>Done</button
|
|
403
|
+
>{/if}
|
|
404
|
+
</div>
|
|
405
|
+
</div>
|