Skip to content
Snippets Groups Projects
Commit 89363462 authored by moon2's avatar moon2 :speech_balloon:
Browse files

clean exit: moon2 apps

parent 1c96a636
No related branches found
No related tags found
1 merge request!218clean exit: moon2 apps
Pipeline #7362 passed
import bl00mbox
blm = bl00mbox.Channel("Melodic Demo")
import leds
from st3m.goose import List, Optional
from st3m.input import InputState, InputController
from st3m.ui.view import ViewManager
from ctx import Context
octave = 0
synths: List[bl00mbox.patches.tinysynth] = []
scale = [0, 2, 4, 5, 7, 9, 11]
def highlight_bottom_petal(num: int, r: int, g: int, b: int) -> None:
start = 4 + 8 * num
for i in range(7):
leds.set_rgb(((i + start) % 40), r, g, b)
def change_playing_field_color(r: int, g: int, b: int) -> None:
highlight_bottom_petal(0, r, g, b)
highlight_bottom_petal(1, r, g, b)
highlight_bottom_petal(3, r, g, b)
highlight_bottom_petal(4, r, g, b)
highlight_bottom_petal(2, 55, 0, 55)
leds.set_rgb(18, 55, 0, 55)
leds.set_rgb(19, 55, 0, 55)
leds.set_rgb(27, 55, 0, 55)
leds.set_rgb(28, 55, 0, 55)
leds.update()
def adjust_playing_field_to_octave() -> None:
global octave
if octave == -1:
change_playing_field_color(0, 0, 55)
elif octave == 0:
change_playing_field_color(0, 27, 27)
elif octave == 1:
change_playing_field_color(0, 55, 0)
def run(input: InputController) -> None:
global scale
global octave
global synths
any_down = False
for i in range(10):
petal = input.captouch.petals[i].whole
if petal.down:
any_down = True
if petal.pressed:
any_down = True
if i == 6:
octave = -1
adjust_playing_field_to_octave()
elif i == 5:
octave = 0
adjust_playing_field_to_octave()
elif i == 4:
octave = 1
adjust_playing_field_to_octave()
else:
k = 10 - i
if k > 3:
k -= 10
k = 3 - k
note = scale[k] + 12 * octave
synths[0].signals.pitch.tone = note
synths[0].signals.trigger.start()
if not any_down:
synths[0].signals.trigger.stop()
def init() -> None:
global synths
for i in range(1):
synth = blm.new(bl00mbox.patches.tinysynth)
synth.signals.output = blm.mixer
synths += [synth]
for synth in synths:
synth.signals.decay = 100
def foreground() -> None:
adjust_playing_field_to_octave()
from st3m.application import Application, ApplicationContext
# TODO(q3k): properly port this app
class MelodicApp(Application):
def __init__(self, app_ctx: ApplicationContext) -> None:
super().__init__(app_ctx)
init()
def draw(self, ctx: Context) -> None:
ctx.rgb(1, 1, 1).rectangle(-120, -120, 240, 240).fill()
ctx.rgb(0, 0, 0)
ctx.scope()
ctx.fill()
def on_enter(self, vm: Optional[ViewManager]) -> None:
super().on_enter(vm)
foreground()
def think(self, ins: InputState, delta_ms: int) -> None:
super().think(ins, delta_ms)
run(self.input)
# For running with `mpremote run`:
if __name__ == "__main__":
import st3m.run
st3m.run.run_view(MelodicApp(ApplicationContext()))
import captouch
import bl00mbox
blm = bl00mbox.Channel("Harmonic Demo")
import leds
from st3m.goose import List
from st3m.input import InputState
from ctx import Context
import cmath
import math
tai = math.tau * 1j
chords = [
[-4, 0, 3, 8, 10],
[-3, 0, 5, 7, 12],
[-1, 2, 5, 7, 11],
[0, 3, 7, 12, 14],
[3, 7, 10, 14, 15],
[[-4, 0, 3, 8, 10], "Fj9"],
[[-3, 0, 5, 7, 12], "D9"],
[[-1, 2, 5, 7, 11], "E7"],
[[0, 3, 7, 12, 14], "A-9"],
[[3, 7, 10, 14, 15], "Cj7"],
]
from st3m.application import Application, ApplicationContext
......@@ -25,10 +29,17 @@ class HarmonicApp(Application):
self.color_intensity = 0.0
self.chord_index = 0
self.chord: List[int] = []
self.synths = [blm.new(bl00mbox.patches.tinysynth) for i in range(5)]
self.chord = None
self.cp_prev = captouch.read()
self.blm = None
self._set_chord(3)
self.prev_captouch = [0] * 10
self.fade = [0] * 5
def _build_synth(self):
if self.blm is None:
self.blm = bl00mbox.Channel("harmonic demo")
self.synths = [self.blm.new(bl00mbox.patches.tinysynth) for i in range(5)]
for i, synth in enumerate(self.synths):
synth.signals.decay = 500
synth.signals.waveform = 0
......@@ -36,10 +47,7 @@ class HarmonicApp(Application):
synth.signals.volume = 0.3 * 32767
synth.signals.sustain = 0.9 * 32767
synth.signals.release = 800
synth.signals.output = blm.mixer
self._set_chord(3)
self.prev_captouch = [0] * 10
synth.signals.output = self.blm.mixer
def _set_chord(self, i: int) -> None:
hue = int(72 * (i + 0.5)) % 360
......@@ -50,34 +58,95 @@ class HarmonicApp(Application):
self.chord = chords[i]
def draw(self, ctx: Context) -> None:
i = self.color_intensity
ctx.rgb(i, i, i).rectangle(-120, -120, 240, 240).fill()
ctx.rgb(0, 0, 0)
ctx.scope()
ctx.fill()
ctx.rgb(0, 0, 0).rectangle(-120, -120, 240, 240).fill()
ctx.line_width = 4
ctx.get_font_name(4)
ctx.text_align = ctx.CENTER
ctx.font_size = 20
for top_petal in range(5):
note_name = self.tone_to_note_name(self.chord[0][top_petal])
note_name = "".join([x for x in note_name if not x.isdigit()])
pos = 95 * cmath.exp(tai * (top_petal - 2.5) / 5)
end_pos = pos * (1 - 0.3j) * 1.2
start_pos = pos * (1 + 0.3j) * 1.2
mid_pos = (start_pos + end_pos) / 8
fade = self.fade[top_petal]
if fade > 0:
ctx.rgb(0, 0, fade)
ctx.move_to(start_pos.imag, start_pos.real)
ctx.quad_to(mid_pos.imag, mid_pos.real, end_pos.imag, end_pos.real)
ctx.fill()
ctx.rgb(1, 0.5, 0)
ctx.move_to(start_pos.imag, start_pos.real)
ctx.quad_to(mid_pos.imag, mid_pos.real, end_pos.imag, end_pos.real)
ctx.stroke()
ctx.move_to(pos.imag, pos.real)
ctx.rgb(1, 0.5, 0)
ctx.text(note_name)
ctx.font_size = 25
ctx.rgb(0, 0.5, 1)
for bottom_petal in range(5):
pos = 90 * cmath.exp(tai * (bottom_petal - 2) / 5)
if bottom_petal == self.chord_index:
pos *= 0.5
ctx.rgb(0, 0.8, 1)
ctx.move_to(pos.imag, pos.real)
ctx.font_size = 35
ctx.text(chords[bottom_petal][1])
ctx.font_size = 25
ctx.rgb(0, 0.5, 1)
else:
ctx.move_to(pos.imag, pos.real)
ctx.text(chords[bottom_petal][1])
def tone_to_note_name(self, tone):
# TODO: add this to radspa helpers
sct = tone * 200 + 18367
return bl00mbox.helpers.sct_to_note_name(sct)
def think(self, ins: InputState, delta_ms: int) -> None:
super().think(ins, delta_ms)
if self.color_intensity > 0:
self.color_intensity -= self.color_intensity / 20
cts = captouch.read()
for i in range(5):
if self.fade[i] > 0:
self.fade[i] -= self.fade[i] * float(delta_ms) / 1000
if self.fade[i] < 0.01:
self.fade[i] = 0
for i in range(10):
if cts.petals[i].pressed and (not self.cp_prev.petals[i].pressed):
j = (10 - i) % 10
if cts.petals[j].pressed and (not self.cp_prev.petals[j].pressed):
if i % 2:
k = int((i - 1) / 2)
self._set_chord(k)
else:
k = int(i / 2)
self.synths[k].signals.pitch.tone = self.chord[k]
self.synths[k].signals.pitch.tone = self.chord[0][k]
self.synths[k].signals.trigger.start()
self.fade[k] = 1
self.color_intensity = 1.0
elif (not cts.petals[i].pressed) and self.cp_prev.petals[i].pressed:
elif (not cts.petals[j].pressed) and self.cp_prev.petals[j].pressed:
if (1 + i) % 2:
k = int(i / 2)
self.synths[k].signals.trigger.stop()
self.cp_prev = cts
def on_enter(self, vm: Optional[ViewManager]) -> None:
# super().on_enter(vm) idk not using it in shoegaze, works fine?
if self.blm is None:
self._build_synth()
self.blm.foreground = True
def on_exit(self):
if self.blm is not None:
self.blm.free = True
self.blm = None
# For running with `mpremote run`:
if __name__ == "__main__":
......
[app]
name = "Harmonic"
name = "harmonic demo"
menu = "Music"
[entry]
......
from st3m.goose import List, Optional
from st3m.input import InputState, InputController
from st3m.ui.view import ViewManager
from st3m.application import Application, ApplicationContext
from ctx import Context
import bl00mbox
import leds
import math
class MelodicApp(Application):
def __init__(self, app_ctx: ApplicationContext) -> None:
super().__init__(app_ctx)
self.synths: List[bl00mbox.patches.tinysynth] = []
self.base_scale = [0, 2, 4, 5, 7, 9, 11]
self.mid_point = 7
self.mid_point_petal = 0
self.mid_point_lock = False
self.mid_point_petal_hyst = 3
self.min_note = -36
self.max_note = +30
self.at_min_note = False
self.at_max_note = False
self.auto_color = (1, 0.5, 1)
self.min_hue = 0
self.max_hue = 0
self.scale = [0] * 10
self.prev_note = None
self.legato = False
self.blm = None
def base_scale_get_val_from_mod_index(self, index):
o = index // len(self.base_scale)
i = index % len(self.base_scale)
return 12 * o + self.base_scale[i]
def base_scale_get_mod_index_from_val(self, val):
val = int(val)
index = val
while True:
try:
i = self.base_scale.index(index % 12)
break
except:
index -= 1
o = val // 12
return i + len(self.base_scale) * o
def make_scale(self):
i = self.base_scale_get_mod_index_from_val(self.mid_point)
for j in range(-5, 5):
tone = self.base_scale_get_val_from_mod_index(i + j)
self.scale[(self.mid_point_petal + j) % 10] = tone
def draw(self, ctx: Context) -> None:
ctx.rgb(0, 0, 0).rectangle(-120, -120, 240, 240).fill()
ctx.text_align = ctx.CENTER
ctx.get_font_name(4)
ctx.font_size = 20
ctx.rgb(0.8, 0.8, 0.8)
ctx.move_to(0, -15)
ctx.text("note shift:")
ctx.font_size = 25
ctx.move_to(0, 15)
if self.mid_point_lock:
ctx.rgb(0, 0.5, 1)
ctx.text("manual")
else:
ctx.rgb(*self.auto_color)
ctx.text("auto")
ctx.rgb(0, 0.5, 1)
ctx.rotate(math.tau * ((self.mid_point_petal / 10) - 0.05))
tmp = ctx.line_width
ctx.line_width = 30
ctx.arc(0, 0, 105, -math.tau * 0.7, math.tau * 0.2, 0).stroke()
if not self.mid_point_lock:
ctx.rgb(*self.auto_color)
if not self.at_max_note:
ctx.arc(0, 0, 105, math.tau * 0.05, math.tau * 0.2, 0).stroke()
if not self.at_min_note:
ctx.arc(0, 0, 105, -math.tau * 0.7, -math.tau * 0.55, 0).stroke()
ctx.line_width = tmp
if self.mid_point_lock:
ctx.rgb(1, 1, 1)
else:
ctx.rgb(0, 0, 0)
ctx.rotate(-math.tau / 10)
if not self.at_max_note:
ctx.move_to(0, 110)
ctx.text("<<<")
ctx.move_to(0, 0)
if not self.at_min_note:
ctx.rotate(math.tau / 5)
ctx.move_to(0, 110)
ctx.text(">>>")
def _build_synth(self):
if self.blm is None:
self.blm = bl00mbox.Channel("melodic demo")
self.synths = []
for i in range(1):
synth = self.blm.new(bl00mbox.patches.tinysynth)
synth.signals.output = self.blm.mixer
self.synths += [synth]
for synth in self.synths:
synth.signals.decay = 100
def update_leds(self):
for i in range(40):
hue_deg = ((i * 90 / 40) + (self.mid_point * 270 / 60) + 180) % 360
if i == 0:
self.hue_min = hue_deg
if i == 39:
self.hue_max = hue_deg
index = i + (self.mid_point_petal - 5) * 4
leds.set_hsv(index % 40, hue_deg, 1, 1)
leds.update()
def on_enter(self, vm: Optional[ViewManager]) -> None:
# super().on_enter(vm) idk not using it in shoegaze, works fine?
if self.blm is None:
self._build_synth()
self.blm.foreground = True
self.make_scale()
def on_exit(self):
if self.blm is not None:
self.blm.free = True
self.blm = None
def shift_playing_field_by_num_petals(self, num):
num_positive = True
if num < 0:
num_positive = False
self.at_max_note = False
elif num > 0:
self.at_min_note = False
num = abs(num)
while num != 0:
if num > 3:
num_part = 3
num -= 3
else:
num_part = num
num = 0
if num_positive:
self.mid_point_petal += num_part
self.mid_point_petal = self.mid_point_petal % 10
else:
self.mid_point_petal -= num_part
self.mid_point_petal = self.mid_point_petal % 10
self.mid_point = self.scale[self.mid_point_petal]
self.make_scale()
# make sure things stay in bounds
while max(self.scale) > self.max_note:
self.mid_point_petal -= 1
self.mid_point_petal = self.mid_point_petal % 10
self.mid_point = self.scale[self.mid_point_petal]
self.make_scale()
self.at_max_note = True
while min(self.scale) < self.min_note:
self.mid_point_petal += 1
self.mid_point_petal = self.mid_point_petal % 10
self.mid_point = self.scale[self.mid_point_petal]
self.make_scale()
self.at_min_note = True
self.make_scale()
if max(self.scale) == self.max_note:
self.at_max_note = True
if min(self.scale) == self.min_note:
self.at_min_note = True
def think(self, ins: InputState, delta_ms: int) -> None:
if self.blm is None:
return
super().think(ins, delta_ms)
petals = []
if self.input.buttons.app.middle.pressed:
self.mid_point_lock = not self.mid_point_lock
if self.input.buttons.app.right.pressed:
self.shift_playing_field_by_num_petals(4)
if self.input.buttons.app.left.pressed:
self.shift_playing_field_by_num_petals(-4)
for i in range(10):
if ins.captouch.petals[i].pressed:
petals += [i]
if len(petals) == 0:
self.synths[0].signals.trigger.stop()
self.prev_note = None
else:
if (len(petals) == 1) and (not self.mid_point_lock):
delta = petals[0] - self.mid_point_petal
if delta > 4:
delta -= 10
if delta < -5:
delta += 10
if delta > 2:
self.shift_playing_field_by_num_petals(delta - 2)
if delta < -3:
self.shift_playing_field_by_num_petals(delta + 3)
avg = 0
for petal in petals:
avg += self.scale[petal]
avg /= len(petals)
self.synths[0].signals.pitch.tone = avg
if (self.legato and self.prev_note is None) or (
(not self.legato) and self.prev_note != avg
):
self.synths[0].signals.trigger.start()
self.prev_note = avg
self.update_leds()
# For running with `mpremote run`:
if __name__ == "__main__":
import st3m.run
st3m.run.run_view(MelodicApp(ApplicationContext()))
[app]
name = "Melodic"
name = "melodic demo"
menu = "Music"
[entry]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment