subsequence 0.6.4__py3-none-any.whl

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.
Files changed (78) hide show
  1. subsequence/__init__.py +231 -0
  2. subsequence/__main__.py +24 -0
  3. subsequence/assets/web/index.html +345 -0
  4. subsequence/cadences.py +113 -0
  5. subsequence/chord_graphs/__init__.py +100 -0
  6. subsequence/chord_graphs/aeolian_minor.py +158 -0
  7. subsequence/chord_graphs/chromatic_mediant.py +113 -0
  8. subsequence/chord_graphs/diminished.py +97 -0
  9. subsequence/chord_graphs/dorian_minor.py +127 -0
  10. subsequence/chord_graphs/functional_major.py +102 -0
  11. subsequence/chord_graphs/hooktheory_major.py +88 -0
  12. subsequence/chord_graphs/lydian_major.py +130 -0
  13. subsequence/chord_graphs/mixolydian.py +98 -0
  14. subsequence/chord_graphs/phrygian_minor.py +76 -0
  15. subsequence/chord_graphs/suspended.py +109 -0
  16. subsequence/chord_graphs/turnaround_global.py +157 -0
  17. subsequence/chord_graphs/whole_tone.py +77 -0
  18. subsequence/chords.py +419 -0
  19. subsequence/composition.py +6099 -0
  20. subsequence/conductor.py +238 -0
  21. subsequence/constants/__init__.py +24 -0
  22. subsequence/constants/durations.py +37 -0
  23. subsequence/constants/instruments/__init__.py +13 -0
  24. subsequence/constants/instruments/gm_cc.py +46 -0
  25. subsequence/constants/instruments/gm_drums.py +53 -0
  26. subsequence/constants/instruments/gm_instruments.py +32 -0
  27. subsequence/constants/instruments/roland_tr8s.py +320 -0
  28. subsequence/constants/instruments/vermona_drm1_drums.py +87 -0
  29. subsequence/constants/midi_notes.py +29 -0
  30. subsequence/constants/pulses.py +17 -0
  31. subsequence/constants/velocity.py +22 -0
  32. subsequence/definitions.py +232 -0
  33. subsequence/display.py +617 -0
  34. subsequence/easing.py +347 -0
  35. subsequence/event_emitter.py +109 -0
  36. subsequence/form_state.py +665 -0
  37. subsequence/forms.py +257 -0
  38. subsequence/groove.py +323 -0
  39. subsequence/harmonic_rhythm.py +83 -0
  40. subsequence/harmonic_state.py +352 -0
  41. subsequence/harmony.py +197 -0
  42. subsequence/held_notes.py +91 -0
  43. subsequence/helpers/__init__.py +0 -0
  44. subsequence/helpers/network.py +58 -0
  45. subsequence/helpers/wing.py +430 -0
  46. subsequence/intervals.py +436 -0
  47. subsequence/keystroke.py +249 -0
  48. subsequence/link_clock.py +128 -0
  49. subsequence/live_client.py +187 -0
  50. subsequence/live_reloader.py +298 -0
  51. subsequence/live_server.py +161 -0
  52. subsequence/melodic_state.py +483 -0
  53. subsequence/midi.py +97 -0
  54. subsequence/midi_utils.py +329 -0
  55. subsequence/mini_notation.py +164 -0
  56. subsequence/motifs.py +2356 -0
  57. subsequence/osc.py +194 -0
  58. subsequence/pattern.py +363 -0
  59. subsequence/pattern_algorithmic.py +2010 -0
  60. subsequence/pattern_builder.py +2589 -0
  61. subsequence/pattern_midi.py +1208 -0
  62. subsequence/progressions.py +1913 -0
  63. subsequence/py.typed +0 -0
  64. subsequence/roles.py +63 -0
  65. subsequence/sequence_utils.py +3123 -0
  66. subsequence/sequencer.py +2086 -0
  67. subsequence/tuning.py +453 -0
  68. subsequence/voicings.py +151 -0
  69. subsequence/web_ui.py +337 -0
  70. subsequence/weighted_graph.py +156 -0
  71. subsequence-0.6.4.dist-info/METADATA +208 -0
  72. subsequence-0.6.4.dist-info/RECORD +78 -0
  73. subsequence-0.6.4.dist-info/WHEEL +5 -0
  74. subsequence-0.6.4.dist-info/entry_points.txt +2 -0
  75. subsequence-0.6.4.dist-info/licenses/LICENSE +661 -0
  76. subsequence-0.6.4.dist-info/scm_file_list.json +193 -0
  77. subsequence-0.6.4.dist-info/scm_version.json +8 -0
  78. subsequence-0.6.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,320 @@
1
+ """Roland TR-8S instrument definition.
2
+
3
+ Note assignments and CC mappings for the Roland TR-8S drum machine.
4
+ Note numbers correspond to the factory default trigger assignments
5
+ for the 11 instrument tracks. CC numbers are from the official MIDI
6
+ Implementation Chart (Version 1.10, 2018-10-04).
7
+
8
+ Three ways to use this module:
9
+
10
+ 1. **As a drum_note_map** - pass ``ROLAND_TR8S_DRUM_MAP`` to the ``drum_note_map``
11
+ parameter of ``@composition.pattern()`` and use track names like ``"bd"``
12
+ or ``"sd"`` in your pattern builder calls::
13
+
14
+ import subsequence.constants.instruments.roland_tr8s as tr8s
15
+
16
+ @composition.pattern(channel=9, beats=4, drum_note_map=tr8s.ROLAND_TR8S_DRUM_MAP)
17
+ def drums (p):
18
+ p.hit_steps("bd", [0, 4, 8, 12], velocity=127)
19
+
20
+ 2. **As a cc_name_map** - pass ``ROLAND_TR8S_CC_MAP`` to the ``cc_name_map``
21
+ parameter of ``@composition.pattern()`` and use human-readable CC names::
22
+
23
+ import subsequence.constants.instruments.roland_tr8s as tr8s
24
+
25
+ @composition.pattern(channel=9, beats=4,
26
+ drum_note_map=tr8s.ROLAND_TR8S_DRUM_MAP,
27
+ cc_name_map=tr8s.ROLAND_TR8S_CC_MAP)
28
+ def drums (p):
29
+ p.hit_steps("bd", [0, 4, 8, 12], velocity=127)
30
+ p.cc("bd_tune", 64)
31
+ p.cc_ramp("bd_decay", 40, 100, shape="ease_in")
32
+
33
+ 3. **As constants** - reference note numbers and CC numbers directly::
34
+
35
+ import subsequence.constants.instruments.roland_tr8s as tr8s
36
+
37
+ p.hit_steps(tr8s.BD, [0, 4, 8, 12], velocity=127)
38
+ p.cc(tr8s.BD_TUNE, 64)
39
+
40
+ ``ROLAND_TR8S_DRUM_MAP`` also accepts General MIDI drum names — the unnumbered
41
+ ``"kick"`` / ``"snare"`` / ``"crash"`` / ``"ride"`` primaries as well as the
42
+ numbered ``"kick_1"``, ``"hi_hat_closed"``, ``"side_stick"``, etc. — as aliases
43
+ for the matching TR-8S voices, a *faithful* subset only, covering the voices
44
+ the machine genuinely has. This lets GM-named patterns play on the TR-8S and
45
+ lets it take part in symbolic mirroring (each device re-resolves a shared drum
46
+ name through its own map). Voices the TR-8S lacks (cowbell, tambourine,
47
+ congas, splash/Chinese cymbals, …) are intentionally not aliased — naming one
48
+ anyway is dropped with a one-time warning (never a wrong voice). Canonical
49
+ GM names come from `pymididefs.drums <https://github.com/simonholliday/PyMidiDefs>`_
50
+ (``GM_DRUM_MAP``).
51
+
52
+ Note: The TR-8S CC assignments are instrument-specific and overlap with
53
+ standard GM CC numbers in incompatible ways (e.g. CC 9 = Shuffle on the
54
+ TR-8S, not a standard GM assignment). This map does NOT extend GM_CC_MAP.
55
+ """
56
+
57
+ import typing
58
+
59
+
60
+ # ═══════════════════════════════════════════════════════════════════════
61
+ # Drum note constants
62
+ # ═══════════════════════════════════════════════════════════════════════
63
+
64
+ BD = 36 # Bass Drum
65
+ SD = 38 # Snare Drum
66
+ LT = 43 # Low Tom
67
+ MT = 47 # Mid Tom
68
+ HT = 50 # High Tom
69
+ RS = 37 # Rim Shot
70
+ HC = 39 # Hand Clap
71
+ CH = 42 # Closed Hi-Hat
72
+ OH = 46 # Open Hi-Hat
73
+ CC = 49 # Crash Cymbal
74
+ RC = 51 # Ride Cymbal
75
+
76
+ # Alternate note numbers (configurable on UTILITY:MIDI:Inst Note)
77
+ BD_ALT = 35
78
+ SD_ALT = 40
79
+ LT_ALT = 41
80
+ MT_ALT = 45
81
+ HT_ALT = 48
82
+ RS_ALT = 56
83
+ HC_ALT = 54
84
+ CH_ALT = 44
85
+ OH_ALT = 55
86
+ CC_ALT = 61
87
+ RC_ALT = 63
88
+
89
+
90
+ # ═══════════════════════════════════════════════════════════════════════
91
+ # CC constants — global controls
92
+ # ═══════════════════════════════════════════════════════════════════════
93
+
94
+ SHUFFLE = 9 # Shuffle amount
95
+ EXTERNAL_IN_LEVEL = 12 # External input level
96
+ AUTO_FILL_IN = 14 # Auto fill in on/off
97
+ MASTER_FX_ON = 15 # Master FX on/off
98
+ DELAY_LEVEL = 16 # Delay send level
99
+ DELAY_TIME = 17 # Delay time
100
+ DELAY_FEEDBACK = 18 # Delay feedback
101
+ MASTER_FX_CTRL = 19 # Master FX control knob
102
+ AUTO_FILL_IN_MANUAL = 70 # Auto fill in manual trigger
103
+ ACCENT = 71 # Accent level
104
+ REVERB_LEVEL = 91 # Reverb send level
105
+
106
+
107
+ # ═══════════════════════════════════════════════════════════════════════
108
+ # CC constants — per-instrument (Tune / Decay / Level / Ctrl)
109
+ # ═══════════════════════════════════════════════════════════════════════
110
+
111
+ # Bass Drum
112
+ BD_TUNE = 20
113
+ BD_DECAY = 23
114
+ BD_LEVEL = 24
115
+ BD_CTRL = 96
116
+
117
+ # Snare Drum
118
+ SD_TUNE = 25
119
+ SD_DECAY = 28
120
+ SD_LEVEL = 29
121
+ SD_CTRL = 97
122
+
123
+ # Low Tom
124
+ LT_TUNE = 46
125
+ LT_DECAY = 47
126
+ LT_LEVEL = 48
127
+ LT_CTRL = 102
128
+
129
+ # Mid Tom
130
+ MT_TUNE = 49
131
+ MT_DECAY = 50
132
+ MT_LEVEL = 51
133
+ MT_CTRL = 103
134
+
135
+ # High Tom
136
+ HT_TUNE = 52
137
+ HT_DECAY = 53
138
+ HT_LEVEL = 54
139
+ HT_CTRL = 104
140
+
141
+ # Rim Shot
142
+ RS_TUNE = 55
143
+ RS_DECAY = 56
144
+ RS_LEVEL = 57
145
+ RS_CTRL = 105
146
+
147
+ # Hand Clap
148
+ HC_TUNE = 58
149
+ HC_DECAY = 59
150
+ HC_LEVEL = 60
151
+ HC_CTRL = 106
152
+
153
+ # Closed Hi-Hat
154
+ CH_TUNE = 61
155
+ CH_DECAY = 62
156
+ CH_LEVEL = 63
157
+ CH_CTRL = 107
158
+
159
+ # Open Hi-Hat
160
+ OH_TUNE = 80
161
+ OH_DECAY = 81
162
+ OH_LEVEL = 82
163
+ OH_CTRL = 108
164
+
165
+ # Crash Cymbal
166
+ CC_TUNE = 83
167
+ CC_DECAY = 84
168
+ CC_LEVEL = 85
169
+ CC_CTRL = 109
170
+
171
+ # Ride Cymbal
172
+ RC_TUNE = 86
173
+ RC_DECAY = 87
174
+ RC_LEVEL = 88
175
+ RC_CTRL = 110
176
+
177
+
178
+ # ═══════════════════════════════════════════════════════════════════════
179
+ # Drum note map
180
+ # ═══════════════════════════════════════════════════════════════════════
181
+
182
+ ROLAND_TR8S_DRUM_MAP: typing.Dict[str, int] = {
183
+ # Native TR-8S track names
184
+ "bd": BD,
185
+ "sd": SD,
186
+ "lt": LT,
187
+ "mt": MT,
188
+ "ht": HT,
189
+ "rs": RS,
190
+ "hc": HC,
191
+ "ch": CH,
192
+ "oh": OH,
193
+ "cc": CC,
194
+ "rc": RC,
195
+
196
+ # General MIDI aliases — *faithful correspondences only*, i.e. GM names for
197
+ # the voices the TR-8S genuinely has. Canonical names come from
198
+ # ``pymididefs.drums`` (``GM_DRUM_MAP``). This lets GM-named patterns play
199
+ # on the TR-8S and lets it take part in symbolic mirroring (each device
200
+ # re-resolves a shared drum name through its own map). Voices the TR-8S
201
+ # lacks (cowbell, tambourine, congas, splash/Chinese cymbals, guiro, …) are
202
+ # deliberately NOT aliased — no creative approximations onto unrelated voices.
203
+ #
204
+ # Unnumbered "primary" aliases (the GM_DRUM_PRIMARY_ALIASES convention from
205
+ # pymididefs.drums): the bare name resolves to the same voice as the _1
206
+ # variant. The TR-8S has a real kick / snare / crash / ride, so all four apply.
207
+ "kick": BD,
208
+ "snare": SD,
209
+ "crash": CC,
210
+ "ride": RC,
211
+
212
+ "kick_1": BD,
213
+ "kick_2": BD,
214
+ "snare_1": SD,
215
+ "snare_2": SD,
216
+ "side_stick": RS, # GM 37 == TR-8S RS 37
217
+ "hand_clap": HC, # GM 39 == TR-8S HC 39
218
+ "hi_hat_closed": CH, # GM 42 == TR-8S CH 42
219
+ "hi_hat_pedal": CH, # foot-closed hat -> the closed hi-hat voice
220
+ "hi_hat_open": OH, # GM 46 == TR-8S OH 46
221
+ "crash_1": CC, # GM 49 == TR-8S CC 49
222
+ "crash_2": CC,
223
+ "ride_1": RC, # GM 51 == TR-8S RC 51
224
+ "ride_2": RC,
225
+
226
+ # GM's six toms onto the TR-8S's three, grouped by register (each TR-8S tom
227
+ # anchored on an exact note match: LT 43, MT 47, HT 50).
228
+ "low_floor_tom": LT,
229
+ "high_floor_tom": LT,
230
+ "low_tom": MT,
231
+ "low_mid_tom": MT,
232
+ "high_mid_tom": HT,
233
+ "high_tom": HT,
234
+ }
235
+
236
+
237
+ # ═══════════════════════════════════════════════════════════════════════
238
+ # CC name map
239
+ # ═══════════════════════════════════════════════════════════════════════
240
+
241
+ ROLAND_TR8S_CC_MAP: typing.Dict[str, int] = {
242
+ # Global controls
243
+ "shuffle": SHUFFLE,
244
+ "external_in_level": EXTERNAL_IN_LEVEL,
245
+ "auto_fill_in": AUTO_FILL_IN,
246
+ "master_fx_on": MASTER_FX_ON,
247
+ "delay_level": DELAY_LEVEL,
248
+ "delay_time": DELAY_TIME,
249
+ "delay_feedback": DELAY_FEEDBACK,
250
+ "master_fx_ctrl": MASTER_FX_CTRL,
251
+ "auto_fill_in_manual": AUTO_FILL_IN_MANUAL,
252
+ "accent": ACCENT,
253
+ "reverb_level": REVERB_LEVEL,
254
+
255
+ # Bass Drum
256
+ "bd_tune": BD_TUNE,
257
+ "bd_decay": BD_DECAY,
258
+ "bd_level": BD_LEVEL,
259
+ "bd_ctrl": BD_CTRL,
260
+
261
+ # Snare Drum
262
+ "sd_tune": SD_TUNE,
263
+ "sd_decay": SD_DECAY,
264
+ "sd_level": SD_LEVEL,
265
+ "sd_ctrl": SD_CTRL,
266
+
267
+ # Low Tom
268
+ "lt_tune": LT_TUNE,
269
+ "lt_decay": LT_DECAY,
270
+ "lt_level": LT_LEVEL,
271
+ "lt_ctrl": LT_CTRL,
272
+
273
+ # Mid Tom
274
+ "mt_tune": MT_TUNE,
275
+ "mt_decay": MT_DECAY,
276
+ "mt_level": MT_LEVEL,
277
+ "mt_ctrl": MT_CTRL,
278
+
279
+ # High Tom
280
+ "ht_tune": HT_TUNE,
281
+ "ht_decay": HT_DECAY,
282
+ "ht_level": HT_LEVEL,
283
+ "ht_ctrl": HT_CTRL,
284
+
285
+ # Rim Shot
286
+ "rs_tune": RS_TUNE,
287
+ "rs_decay": RS_DECAY,
288
+ "rs_level": RS_LEVEL,
289
+ "rs_ctrl": RS_CTRL,
290
+
291
+ # Hand Clap
292
+ "hc_tune": HC_TUNE,
293
+ "hc_decay": HC_DECAY,
294
+ "hc_level": HC_LEVEL,
295
+ "hc_ctrl": HC_CTRL,
296
+
297
+ # Closed Hi-Hat
298
+ "ch_tune": CH_TUNE,
299
+ "ch_decay": CH_DECAY,
300
+ "ch_level": CH_LEVEL,
301
+ "ch_ctrl": CH_CTRL,
302
+
303
+ # Open Hi-Hat
304
+ "oh_tune": OH_TUNE,
305
+ "oh_decay": OH_DECAY,
306
+ "oh_level": OH_LEVEL,
307
+ "oh_ctrl": OH_CTRL,
308
+
309
+ # Crash Cymbal
310
+ "cc_tune": CC_TUNE,
311
+ "cc_decay": CC_DECAY,
312
+ "cc_level": CC_LEVEL,
313
+ "cc_ctrl": CC_CTRL,
314
+
315
+ # Ride Cymbal
316
+ "rc_tune": RC_TUNE,
317
+ "rc_decay": RC_DECAY,
318
+ "rc_level": RC_LEVEL,
319
+ "rc_ctrl": RC_CTRL,
320
+ }
@@ -0,0 +1,87 @@
1
+ """Vermona DRM1 MKIV drum note map.
2
+
3
+ Note assignments for the Vermona DRM1 analog drum synthesizer.
4
+ These note numbers correspond to the factory default trigger assignments.
5
+
6
+ Two ways to use this module:
7
+
8
+ 1. **As a drum_note_map** - pass ``VERMONA_DRM1_DRUM_MAP`` to the ``drum_note_map`` parameter
9
+ of ``@composition.pattern()`` and use human-readable names like ``"kick"``
10
+ or ``"snare"`` in your pattern builder calls::
11
+
12
+ import subsequence.constants.instruments.vermona_drm1_drums as drm1
13
+
14
+ @composition.pattern(channel=10, beats=4, drum_note_map=drm1.VERMONA_DRM1_DRUM_MAP)
15
+ def drums (p):
16
+ p.hit_steps("kick", [0, 4, 8, 12], velocity=127)
17
+
18
+ 2. **As constants** - reference note numbers directly::
19
+
20
+ import subsequence.constants.instruments.vermona_drm1_drums as drm1
21
+
22
+ @composition.pattern(channel=10, beats=4)
23
+ def drums (p):
24
+ p.hit_steps(drm1.KICK, [0, 4, 8, 12], velocity=127)
25
+
26
+ ``VERMONA_DRM1_DRUM_MAP`` also accepts a *faithful* subset of General MIDI drum
27
+ names (e.g. ``"kick_1"``, ``"snare_1"``, ``"hi_hat_closed"``) as aliases — only
28
+ for the voices the DRM1 genuinely has (kick, snare, clap, hi-hats). These
29
+ shared GM names are what let the DRM1 take part in symbolic mirroring (each
30
+ device re-resolves a drum name through its own map). GM names for instruments
31
+ the DRM1 lacks (toms, ride/crash cymbals, shakers, cowbell and other latin/aux
32
+ percussion) are intentionally NOT aliased — naming one anyway is dropped with
33
+ a one-time warning (never a wrong voice); address those by their native
34
+ ``drum_1`` / ``drum_2`` / ``multi`` names. Canonical GM names come from
35
+ `pymididefs.drums <https://github.com/simonholliday/PyMidiDefs>`_ (``GM_DRUM_MAP``).
36
+ """
37
+
38
+ import typing
39
+
40
+
41
+ # ─── Individual note constants ───────────────────────────────────────
42
+
43
+ KICK = 36 # C2
44
+ DRUM_1 = 45 # A2
45
+ DRUM_2 = 50 # D3
46
+ MULTI = 56 # G#3
47
+ SNARE = 38 # D2
48
+ HIHAT_1_CLOSED = 44 # G#2
49
+ HIHAT_1_OPEN = 46 # A#2 (Cymbal)
50
+ HIHAT_2_CLOSED = 49 # C#3
51
+ HIHAT_2_OPEN = 51 # D#3 (Cymbal)
52
+ CLAP = 39 # D#2
53
+
54
+
55
+ # ─── Complete drum note map ──────────────────────────────────────────
56
+
57
+ VERMONA_DRM1_DRUM_MAP: typing.Dict[str, int] = {
58
+ # Native DRM1 mapping
59
+ "kick": KICK,
60
+ "drum_1": DRUM_1,
61
+ "drum_2": DRUM_2,
62
+ "multi": MULTI,
63
+ "snare": SNARE,
64
+ "hihat_1_closed": HIHAT_1_CLOSED,
65
+ "hihat_1_open": HIHAT_1_OPEN,
66
+ "hihat_2_closed": HIHAT_2_CLOSED,
67
+ "hihat_2_open": HIHAT_2_OPEN,
68
+ "clap": CLAP,
69
+
70
+ # General MIDI aliases — *faithful correspondences only*, i.e. GM names for
71
+ # the voices the DRM1 genuinely has. Canonical names come from
72
+ # ``pymididefs.drums`` (``GM_DRUM_MAP``); this is the shared vocabulary used
73
+ # by symbolic mirroring (each device re-resolves a drum name through its own
74
+ # map). GM names for instruments the DRM1 lacks — toms, ride/crash cymbals,
75
+ # shakers, and latin/aux percussion — are deliberately NOT aliased: a
76
+ # "creative approximation" onto an unrelated voice (cowbell -> multi,
77
+ # cymbal -> hi-hat) was an over-reach. Use the native ``drum_1`` /
78
+ # ``drum_2`` / ``multi`` names for those instead.
79
+ "kick_1": KICK,
80
+ "kick_2": KICK,
81
+ "snare_1": SNARE,
82
+ "snare_2": SNARE,
83
+ "hand_clap": CLAP, # GM 39 == DRM1 CLAP 39
84
+ "hi_hat_closed": HIHAT_1_CLOSED,
85
+ "hi_hat_pedal": HIHAT_1_CLOSED, # foot-closed hat -> the closed hi-hat voice
86
+ "hi_hat_open": HIHAT_1_OPEN,
87
+ }
@@ -0,0 +1,29 @@
1
+ """MIDI note number constants.
2
+
3
+ Maps note names to their MIDI note numbers (0–127). Convention: **C4 = 60** (Middle C),
4
+ matching the MIDI Manufacturers Association standard and most DAWs (Ableton, Logic, Reaper).
5
+
6
+ Notes are named ``<Pitch><Octave>`` for naturals and ``<Pitch>S<Octave>`` for sharps::
7
+
8
+ import subsequence.constants.midi_notes as notes
9
+
10
+ p.note(notes.A4, velocity=100) # 69
11
+ p.arpeggio(chord.tones(notes.E2)) # 40
12
+ root = notes.C3 # 48
13
+
14
+ Range: C_NEG1 (0) through G9 (127). Sharps are provided (e.g. ``CS4`` for C♯4);
15
+ flats are enharmonic equivalents (Db4 == CS4 == 61).
16
+
17
+ Canonical source: `pymididefs <https://github.com/simonholliday/PyMidiDefs>`_.
18
+ """
19
+
20
+ # Re-export everything from pymididefs.notes — all note constants (C_NEG1..G9),
21
+ # lookup tables, and conversion functions.
22
+ from pymididefs.notes import * # noqa: F401,F403
23
+ from pymididefs.notes import ( # noqa: F401 — explicit re-exports for type checkers
24
+ NOTE_CLASSES,
25
+ NOTE_NAMES,
26
+ SEMITONE_MAP,
27
+ name_to_note,
28
+ note_to_name,
29
+ )
@@ -0,0 +1,17 @@
1
+ """Pulse-based MIDI timing constants.
2
+
3
+ The sequencer uses **24 pulses per quarter note** (PPQN = 24) as its internal time base.
4
+ These constants represent the number of pulses for each standard note duration.
5
+
6
+ These are used internally by the sequencer engine. Pattern builders work in beats
7
+ (see ``subsequence.constants.durations`` for beat-based constants).
8
+ """
9
+
10
+ # MIDI Standards - number of pulses in each
11
+
12
+ MIDI_THIRTYSECOND_NOTE = 3
13
+ MIDI_SIXTEENTH_NOTE = 6
14
+ MIDI_EIGHTH_NOTE = 12
15
+ MIDI_QUARTER_NOTE = 24
16
+ MIDI_HALF_NOTE = 48
17
+ MIDI_WHOLE_NOTE = 96
@@ -0,0 +1,22 @@
1
+ """MIDI velocity constants.
2
+
3
+ Velocity is the MIDI attack strength (0-127). These constants define sensible
4
+ defaults for different musical contexts.
5
+ """
6
+
7
+ # Primary defaults
8
+ DEFAULT_VELOCITY = 100 # Most notes, hits, arpeggios
9
+ DEFAULT_CHORD_VELOCITY = 90 # Chords and harmonic content (softer)
10
+
11
+ # Generative / texture defaults — named so these values don't scatter as raw literals
12
+ DEFAULT_GENERATIVE_VELOCITY = 80 # Generative melodic lines (lsystem, de_bruijn, evolve, branch, lorenz, …)
13
+ DEFAULT_CA_VELOCITY = 60 # Cellular automata (cellular_1d / cellular_2d)
14
+ GHOST_FILL_VELOCITY = 35 # Deliberately soft ghost-note layer
15
+
16
+ # Velocity shaping boundaries
17
+ VELOCITY_SHAPE_LOW = 64
18
+ VELOCITY_SHAPE_HIGH = 127
19
+
20
+ # MIDI standard range
21
+ MIN_VELOCITY = 0
22
+ MAX_VELOCITY = 127