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

shoegaze: enable chord borrowing from chord organ

harmonic demo: rename to chord organ in flow3r.toml only,
add "tones_readonly" chord tone information to savefile
parent 2c72def7
No related branches found
No related tags found
No related merge requests found
...@@ -88,7 +88,7 @@ We ship some noise-making apps by default: ...@@ -88,7 +88,7 @@ We ship some noise-making apps by default:
shoegaze shoegaze
^^^^^^^^ ^^^^^^^^
Electric guitar simulator with fuzz and reverb. Tilt for wiggle stick. App button middle switches between render modes: Lo Fi has lower framerate, default has slower input response time. App button left turns delay on and off. Top petals play notes in chord, bottom petals change chord. Electric guitar simulator with fuzz and reverb. Tilt for wiggle stick. Top petals play notes in chord, bottom petals change chord. App button left turns delay on and off, app button right checks for chords in the savefile of chord organ and toggles between them if found.
Otamatone Otamatone
^^^^^^^^^ ^^^^^^^^^
...@@ -112,8 +112,8 @@ be reset when passing it, if they're "open" they let the sequencer pass through ...@@ -112,8 +112,8 @@ be reset when passing it, if they're "open" they let the sequencer pass through
Your beat is saved in flash at ``/sys/gay_drums.json`` when exiting gay drums! Make sure to wait until the menu screen appears before turning the power off though :D! Your beat is saved in flash at ``/sys/gay_drums.json`` when exiting gay drums! Make sure to wait until the menu screen appears before turning the power off though :D!
harmonic demo chord organ
^^^^^^^^^^^^^ ^^^^^^^^^^^
A chord organ! The top petals always play the 5 notes of the selected chord. A chord organ! The top petals always play the 5 notes of the selected chord.
...@@ -146,7 +146,7 @@ Samples are saved in flash at ``/sys/samples/tiny_sample_*.wav``. ...@@ -146,7 +146,7 @@ Samples are saved in flash at ``/sys/samples/tiny_sample_*.wav``.
.. _usage_apps: .. _usage_apps:
Applications Apps
------------ ------------
Audio passthrough Audio passthrough
......
...@@ -305,6 +305,7 @@ class HarmonicApp(Application): ...@@ -305,6 +305,7 @@ class HarmonicApp(Application):
chord["nine"] = self.chords[i].nine chord["nine"] = self.chords[i].nine
chord["root"] = self.chords[i].root chord["root"] = self.chords[i].root
chord["voicing"] = self.chords[i].voicing chord["voicing"] = self.chords[i].voicing
chord["tones_readonly"] = self.chords[i].notes
if not file_is_different: if not file_is_different:
user_chord = user_settings["chords"][i] user_chord = user_settings["chords"][i]
if self._file_settings is None: if self._file_settings is None:
......
[app] [app]
name = "harmonic demo" name = "chord organ"
menu = "Music" menu = "Music"
[entry] [entry]
......
...@@ -5,6 +5,7 @@ from st3m.input import InputState ...@@ -5,6 +5,7 @@ from st3m.input import InputState
from ctx import Context from ctx import Context
import json import json
import errno
import math import math
import captouch import captouch
import bl00mbox import bl00mbox
...@@ -33,7 +34,7 @@ class ShoegazeApp(Application): ...@@ -33,7 +34,7 @@ class ShoegazeApp(Application):
self.blm: Optional[bl00mbox.Channel] = None self.blm: Optional[bl00mbox.Channel] = None
self.chord_index = 0 self.chord_index = 0
self.chord: List[int] = [] self.chord: List[int] = []
self._set_chord(3) self._organ_chords = [None] * 5
self._tilt_bias = 0.0 self._tilt_bias = 0.0
self._detune_prev = 0.0 self._detune_prev = 0.0
self._git_string_tuning = [0] * 4 self._git_string_tuning = [0] * 4
...@@ -43,8 +44,8 @@ class ShoegazeApp(Application): ...@@ -43,8 +44,8 @@ class ShoegazeApp(Application):
self._rand_limit = 16 self._rand_limit = 16
self._rand_rot = 0.0 self._rand_rot = 0.0
self.delay_on = True self.delay_on = True
self.fuzz_on = True self.organ_on = False
self._lofi = False self._set_chord(3)
def _build_synth(self) -> None: def _build_synth(self) -> None:
if self.blm is None: if self.blm is None:
...@@ -95,50 +96,63 @@ class ShoegazeApp(Application): ...@@ -95,50 +96,63 @@ class ShoegazeApp(Application):
self.main_mixer.signals.gain = 2000 self.main_mixer.signals.gain = 2000
self.main_lp.signals.reso = 2000 self.main_lp.signals.reso = 2000
self._update_connections()
def _update_connections(self) -> None:
if self.blm is None:
return
if self.fuzz_on:
self.bass_lp.signals.gain = 32767 self.bass_lp.signals.gain = 32767
self.git_lp.signals.gain = 32767 self.git_lp.signals.gain = 32767
self.main_lp.signals.freq = 2500 self.main_lp.signals.freq = 2500
self.main_lp.signals.gain = 2000 self.main_lp.signals.gain = 2000
self.git_mixer.signals.gain = 4000 self.git_mixer.signals.gain = 4000
self.main_lp.signals.input = self.main_fuzz.signals.output self.main_lp.signals.input = self.main_fuzz.signals.output
self._update_connections()
def _update_connections(self) -> None:
if self.blm is None:
return
if self.delay_on: if self.delay_on:
self.git_delay.signals.input = self.git_fuzz.signals.output self.git_delay.signals.input = self.git_fuzz.signals.output
self.main_mixer.signals.input0 = self.git_delay.signals.output self.main_mixer.signals.input0 = self.git_delay.signals.output
else: else:
self.main_mixer.signals.input0 = self.git_fuzz.signals.output self.main_mixer.signals.input0 = self.git_fuzz.signals.output
else:
self.bass_lp.signals.gain = 2000
self.git_lp.signals.gain = 2000
self.main_lp.signals.freq = 6000
self.main_lp.signals.gain = 4000
self.git_mixer.signals.gain = 500
self.main_lp.signals.input = self.main_mixer.signals.output
if self.delay_on:
self.git_delay.signals.input = self.git_lp.signals.output
self.main_mixer.signals.input0 = self.git_delay.signals.output
else:
self.main_mixer.signals.input0 = self.git_lp.signals.output
def fuzz_toggle(self) -> None: def _try_load_settings(self, path):
self.fuzz_on = not self.fuzz_on try:
self._update_connections() with open(path, "r") as f:
return json.load(f)
except OSError as e:
if e.errno != errno.ENOENT:
raise # ignore file not found
def _load_settings(self):
settings_path = "/flash/harmonic_demo.json"
settings = self._try_load_settings(settings_path)
if settings is not None:
for i, chord in enumerate(settings["chords"]):
if i > 4:
break
self._organ_chords[i] = chord["tones_readonly"]
def organ_toggle(self) -> None:
self.organ_on = not self.organ_on
if self.organ_on and self._organ_chords[0] is None:
self._load_settings()
if self._organ_chords[0] is None:
self.organ_on = False
self._set_chord(self.chord_index, force_update=True)
def delay_toggle(self) -> None: def delay_toggle(self) -> None:
self.delay_on = not self.delay_on self.delay_on = not self.delay_on
self._update_connections() self._update_connections()
def _set_chord(self, i: int) -> None: def _set_chord(self, i: int, force_update=False) -> None:
hue = int(54 * (i + 0.5)) % 360 hue = int(54 * (i + 0.5)) % 360
if i != self.chord_index: if i != self.chord_index or force_update:
self.chord_index = i self.chord_index = i
leds.set_all_hsv(hue, 1, 0.2) leds.set_all_hsv(hue, 1, 0.2)
leds.update() leds.update()
if self.organ_on and self._organ_chords[i] is not None:
self.chord = self._organ_chords[i]
else:
self.chord = chords[i] self.chord = chords[i]
def draw(self, ctx: Context) -> None: def draw(self, ctx: Context) -> None:
...@@ -159,38 +173,46 @@ class ShoegazeApp(Application): ...@@ -159,38 +173,46 @@ class ShoegazeApp(Application):
ctx.text("bass") ctx.text("bass")
rot = self._spinny # + self._detune_prev rot = self._spinny # + self._detune_prev
ctx.rgb(0, 0.5, 0.5)
ctx.rotate(rot + self._rand_rot) ctx.rotate(rot + self._rand_rot)
if self.organ_on:
ctx.rgb(0.5, 0, 0.6)
ctx.rotate(0.69)
ctx.move_to(0, -10)
ctx.text("chordorganchordorganchord")
ctx.move_to(0, 10)
ctx.text("organchordorganchordorgan")
ctx.rotate(4.20 + 0.69)
else:
ctx.rgb(0, 0.5, 0.5)
ctx.move_to(0, -10) ctx.move_to(0, -10)
ctx.text("shoegazeshoegazeshoe") ctx.text("shoegazeshoegazeshoe")
ctx.move_to(0, 10) ctx.move_to(0, 10)
ctx.text("gazeshoegazeshoegaze") ctx.text("gazeshoegazeshoegaze")
ctx.rotate(-2.2 * (rot + self._rand_rot) - 0.5) ctx.rotate(-2.2 * (rot + self._rand_rot) - 0.5)
if self.organ_on:
rgb = (0.7, 0.7, 0)
else:
rgb = (0, 0.8, 0)
ctx.move_to(40, 40) ctx.move_to(40, 40)
if self.delay_on: if self.delay_on:
ctx.rgb(0, 0.8, 0) ctx.rgb(*rgb)
ctx.text("delay ON!") ctx.text("delay ON!")
else: else:
ctx.rgb(0, 0.6, 0) ctx.rgb(*tuple([x * 0.75 for x in rgb]))
ctx.text("delay off") ctx.text("delay off")
ctx.rgb(*rgb)
ctx.rotate(0.2 + self._rand_rot) ctx.rotate(0.2 + self._rand_rot)
ctx.move_to(50, -50) ctx.move_to(50, -50)
detune = "detune: " + str(int(self._detune_prev * 100)) detune = "detune: " + str(int(self._detune_prev * 100))
ctx.rgb(0, 0.8, 0) ctx.rgb(*rgb)
ctx.text(detune) ctx.text(detune)
ctx.rotate(-2.5 * (rot + 4 * self._rand_rot)) ctx.rotate(-2.5 * (rot + 4 * self._rand_rot))
ctx.move_to(-50, 50) ctx.move_to(-50, 50)
if self.fuzz_on:
ctx.rgb(0, 0.8, 0)
ctx.text("fuzz ON!") ctx.text("fuzz ON!")
else:
ctx.rgb(0, 0.6, 0)
ctx.text("fuzz off")
def think(self, ins: InputState, delta_ms: int) -> None: def think(self, ins: InputState, delta_ms: int) -> None:
super().think(ins, delta_ms) super().think(ins, delta_ms)
...@@ -208,10 +230,7 @@ class ShoegazeApp(Application): ...@@ -208,10 +230,7 @@ class ShoegazeApp(Application):
if buttons.app.right.pressed: if buttons.app.right.pressed:
self.delay_toggle() self.delay_toggle()
if buttons.app.left.pressed: if buttons.app.left.pressed:
pass self.organ_toggle()
# self.fuzz_toggle()
if buttons.app.middle.pressed:
self.lofi = not self.lofi
for i in range(1, 10, 2): for i in range(1, 10, 2):
if petals[i].whole.pressed: if petals[i].whole.pressed:
...@@ -235,21 +254,8 @@ class ShoegazeApp(Application): ...@@ -235,21 +254,8 @@ class ShoegazeApp(Application):
self.bass_string.decay = 1000 self.bass_string.decay = 1000
self.bass_string.signals.trigger.start() self.bass_string.signals.trigger.start()
@property
def lofi(self):
return self._lofi
@lofi.setter
def lofi(self, val):
self._lofi = bool(val)
if self._lofi:
sys_display.set_mode(2313)
else:
sys_display.set_mode(912)
def on_enter(self, vm: Optional[ViewManager]) -> None: def on_enter(self, vm: Optional[ViewManager]) -> None:
super().on_enter(vm) super().on_enter(vm)
self.lofi = self.lofi
if self.blm is None: if self.blm is None:
self._build_synth() self._build_synth()
self.blm.foreground = True self.blm.foreground = True
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment