Skip to content

Commit 473c360

Browse files
committed
Detect x axis vibrato on launchpad... WTF!?
1 parent d01221c commit 473c360

8 files changed

Lines changed: 2385 additions & 2159 deletions

File tree

midimech.py

Lines changed: 7 additions & 2158 deletions
Large diffs are not rendered by default.

src/articulation.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
from enum import Enum
2+
from src.util import sign
3+
from src.constants import *
4+
5+
class Articulation:
6+
State = Enum('state', 'off pre attack hold release')
7+
8+
def __init__(self, core):
9+
self.core = core
10+
self.value = 0.0
11+
self.time_between_ticks = 0.05
12+
self.timer = 0.0
13+
self.state = self.State(self.State.off)
14+
15+
# a list of midi notes that need to be released
16+
self.deferred_notes = set()
17+
# self.noise_ = 0.0
18+
# self.last_noise = 0.0
19+
20+
self.vibrato_low = 0.75
21+
self.vibrato_high = 0.85
22+
self.vibrato_dir = 0.0
23+
self.vibrato_window_t = 0.0
24+
self.vibrato_window = 0.5
25+
self.pressure_ = 0.0
26+
self.wiggles = 0
27+
28+
self.mod = 0.0
29+
self.mod_changed = True
30+
31+
def pressure(self, value):
32+
if not value or value <= 0.0:
33+
self.pressure_ = value
34+
self.wiggles = 0
35+
self.vibrato_dir = 1.0
36+
self.vibrato_window_t = 0.0
37+
return
38+
if self.pressure_ == 0.0: # was off, now on
39+
self.vibrato_dir = 1.0
40+
self.wiggles = 0
41+
self.pressure_ = value
42+
if value <= self.vibrato_low:
43+
if self.vibrato_dir <= 0.0:
44+
self.vibrato_dir = 1.0
45+
if value >= self.vibrato_high:
46+
if self.vibrato_dir >= 0.0:
47+
self.vibrato_window_t = self.vibrato_window
48+
self.vibrato_dir = -1.0
49+
self.wiggles += 1
50+
51+
def change_state(self, new_state):
52+
if new_state == self.state:
53+
return
54+
if new_state == self.state.pre:
55+
self.state = new_state
56+
return
57+
if new_state == self.state.attack:
58+
self.state = new_state
59+
return
60+
if new_state == self.state.hold:
61+
self.state = new_state
62+
return
63+
if new_state == self.state.release:
64+
self.state = new_state
65+
return
66+
67+
def release(self):
68+
self.change_state(self.state.release)
69+
70+
def stop(self):
71+
self.change_state(self.state.off)
72+
73+
def defer_midi_note(self, note):
74+
self.notes.add(note)
75+
76+
def set(self, value):
77+
if self.value is False or self.value <= 0.0:
78+
if self.state != self.state.off:
79+
self.change_state(self.state.release)
80+
81+
self.value = value or 0.0
82+
83+
if self.state == self.state.off:
84+
self.change_state(self.state.pre)
85+
86+
def tick(self):
87+
# if self.state == self.state.off:
88+
# return
89+
90+
if self.mod_changed:
91+
self.core.midi_write(self.core.midi_out, [0xb0, 1, int(self.mod * 127)])
92+
self.mod_changed = False
93+
94+
# held_note_count = self.core.held_note_count()
95+
# if held_note_count == 0:
96+
# pass
97+
98+
def logic(self, dt):
99+
self.timer += dt
100+
101+
self.vibrato_window_t = max(0.0, self.vibrato_window_t - 1.0 * dt)
102+
if self.vibrato_window_t <= 0.0:
103+
self.vibrato_length = 0.0
104+
self.wiggles = 0
105+
if self.mod >= 0.0:
106+
self.mod = 0.0
107+
self.mod_changed = True
108+
elif self.wiggles >= 2:
109+
if self.mod < 1.0:
110+
self.mod = min(1.0, self.mod + 1.0 * dt)
111+
self.mod_changed = True
112+
else:
113+
if self.mod > 0.0:
114+
self.mod = max(0.0, self.mod - 1.0 * dt)
115+
self.mod_changed = True
116+
117+
if self.timer >= self.time_between_ticks:
118+
self.timer -= self.time_between_ticks
119+
120+
# we're losing time
121+
if self.timer >= self.time_between_ticks:
122+
self.timer = 0.0
123+
124+
self.tick()
125+

src/constants.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from glm import ivec2, vec2, ivec3, vec3
2+
3+
TITLE = "midimech"
4+
# FOCUS = False
5+
NOTES = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
6+
WHOLETONE = True
7+
FONT_SZ = 32
8+
BRIGHTNESS = 0.4
9+
C_COLOR = ivec3(0, 128 * BRIGHTNESS, 0)
10+
YELLOW = ivec3(205 * BRIGHTNESS, 127 * BRIGHTNESS, 0)
11+
LIGHT = ivec3(0, 0, 128 * BRIGHTNESS)
12+
FGAB = ivec3(64 * BRIGHTNESS)
13+
GRAY = ivec3(16 * BRIGHTNESS)
14+
BORDER_COLOR = ivec3(48)
15+
DARK = ivec3(0)
16+
BASE_OFFSET = -4 # linnstrument
17+
# CHORD_ANALYZER = get_option(opts,'chord_analyzer',False)
18+
EPSILON = 0.0001
19+
FADE_SPEED = 4.0
20+
21+
COLOR_CODES = [
22+
ivec3(0), # default color
23+
ivec3(255, 0, 0), # red
24+
ivec3(205, 205, 0), # yellow
25+
ivec3(0, 127, 0), # green
26+
ivec3(0, 127, 127), # cyan
27+
ivec3(0, 0, 128), # blue
28+
ivec3(159, 43, 104), # purple
29+
ivec3(0), # off
30+
ivec3(80, 80, 80), # gray
31+
ivec3(255, 127, 0), # orange
32+
ivec3(0, 255, 0), # lime
33+
ivec3(255, 127, 127), # pink
34+
]
35+
36+
# NOTE_COLORS = [
37+
# ivec3(255, 0, 0), # C
38+
# ivec3(255/2, 0, 0), # C#
39+
# ivec3(255, 127, 0), # D
40+
# ivec3(255/2, 127/2, 0), # D#
41+
# ivec3(255, 255, 0), # E
42+
# ivec3(0, 255, 0), # F
43+
# ivec3(0, 255/2, 0), # F#
44+
# ivec3(0, 0, 255), # G
45+
# ivec3(0, 0, 255/2), # G#
46+
# ivec3(128, 0, 128), # A
47+
# ivec3(128/2, 0, 128/2), # A#
48+
# ivec3(255, 0, 255) # B
49+
# ]

0 commit comments

Comments
 (0)