Skip to content
Snippets Groups Projects
Select Git revision
  • c00a3a8b5d6e8c4fc56fe4a54d82808f291ebcda
  • main default protected
  • phhw
  • captouch-threshold
  • t
  • dos
  • test2
  • test
  • slewtest
  • simtest
  • view-think
  • vm-pending
  • media-buf
  • scope
  • passthrough
  • wave
  • vsync
  • dos-main-patch-50543
  • json-error
  • rahix/big-flow3r
  • pippin/media_framework
  • v1.3.0
  • v1.2.0
  • v1.2.0+rc1
  • v1.1.1
  • v1.1.0
  • v1.1.0+rc1
  • v1.0.0
  • v1.0.0+rc6
  • v1.0.0+rc5
  • v1.0.0+rc4
  • v1.0.0+rc3
  • v1.0.0+rc2
  • v1.0.0+rc1
34 results

_patches.py

Blame
  • Forked from flow3r / flow3r firmware
    998 commits behind the upstream repository.
    _patches.py 8.32 KiB
    # SPDX-License-Identifier: CC0-1.0
    import math
    
    import bl00mbox
    
    try:
        import cpython.wave as wave
    except ImportError:
        wave = None
    
    
    class _Patch:
        def bl00mbox_patch_marker(self):
            return True
    
    
    class _PatchSignalList:
        pass
    
    
    class _PatchBudList:
        pass
    
    
    class tinysynth(_Patch):
        def __init__(self, chan):
            self.channel = chan
            self.SINE = -32767
            self.TRI = -1
            self.SQUARE = 1
            self.SAW = 32767
    
            self.osc = chan.new_bud(420)
            self.env = chan.new_bud(42)
            self.amp = chan.new_bud(69)
            self.amp.signals.output.value = chan.mixer
            self.amp.signals.gain.value = self.env.signals.output
            self.amp.signals.input.value = self.osc.signals.output
            self.env.signals.sustain.value = 0
            self.env.signals.decay.value = 500
            self.release(100)
    
        def __repr__(self):
            ret = "[patch] tinysynth"
            ret += "\n  " + "\n  ".join(repr(self.osc).split("\n"))
            ret += "\n  " + "\n  ".join(repr(self.env).split("\n"))
            ret += "\n  " + "\n  ".join(repr(self.amp).split("\n"))
            return ret
    
        def tone(self, val):
            self.osc.signals.pitch.tone = val
    
        def freq(self, val):
            self.osc.signals.pitch.freq = val
    
        def volume(self, val):
            self.env.signals.input.value = 32767 * val
    
        def start(self):
            self.env.signals.trigger.start()
    
        def stop(self):
            self.env.signals.trigger.stop()
    
        def waveform(self, val):
            self.osc.signals.waveform.value = val
    
        def attack(self, val):
            self.env.signals.attack.value = val
    
        def decay(self, val):
            self.env.signals.decay.value = val
    
        def sustain(self, val):
            self.env.signals.sustain.value = val * 32767
    
        def release(self, val):
            self.env.signals.release.value = val
    
    
    class tinysynth_fm(tinysynth):
        def __init__(self, chan):
            tinysynth.__init__(self, chan)
            self.mod_osc = chan.new_bud(420)
            self.fm_mult = 2.5
            self.mod_osc.signals.output.value = self.osc.signals.lin_fm
            self.decay(1000)
            self.attack(20)
            self._update_mod_osc()
            self.fm_waveform(self.SQUARE)
            self.waveform(self.TRI)
    
        def fm_waveform(self, val):
            self.mod_osc.signals.waveform.value = val
    
        def __repr__(self):
            ret = tinysynth.__repr__(self)
            ret = ret.split("\n")
            ret[0] += "_fm"
            ret = "\n".join(ret)
            ret += "\n  " + "\n  ".join(repr(self.mod_osc).split("\n"))
            return ret
    
        def fm(self, val):
            self.fm_mult = val
            self._update_mod_osc()
    
        def tone(self, val):
            self.osc.signals.pitch.tone = val
            self._update_mod_osc()
    
        def freq(self, val):
            self.osc.signals.pitch.freq = val
            self._update_mod_osc()
    
        def _update_mod_osc(self):
            self.mod_osc.signals.pitch.freq = self.fm_mult * self.osc.signals.pitch.freq
    
    
    class sampler(_Patch):
        """needs a wave file with path relative to samples/"""
    
        def __init__(self, chan, filename):
            if wave is None:
                pass
                # raise Bl00mboxError("wave library not found")
            f = wave.open("/flash/sys/samples/" + filename, "r")
            len_frames = f.getnframes()
            self.sampler = chan.new_bud(696969, len_frames)
            table = [0] * len_frames
            for i in range(len_frames):
                frame = f.readframes(1)
                value = int.from_bytes(frame[0:2], "little")
                table[i] = value
            f.close()
            self._filename = filename
            self.sampler.table = table
            self.sampler.signals.output = chan.mixer
    
        def start(self):
            self.sampler.signals.trigger.start()
    
        def stop(self):
            self.sampler.signals.trigger.stop()
    
        @property
        def filename(self):
            return self._filename
    
    
    class step_sequencer(_Patch):
        def __init__(self, chan):
            self.seqs = []
            for i in range(4):
                seq = chan.new_bud(56709)
                seq.table = [-32767] + ([0] * 16)
                if len(self.seqs):
                    self.seqs[-1].signals.sync_out = seq.signals.sync_in
                self.seqs += [seq]
            self._bpm = 120
    
        def __repr__(self):
            ret = "[patch] step sequencer"
            # ret += "\n  " + "\n  ".join(repr(self.seqs[0]).split("\n"))
            ret += (
                "\n  bpm: "
                + str(self.seqs[0].signals.bpm.value)
                + " @ 1/"
                + str(self.seqs[0].signals.beat_div.value)
            )
            ret += (
                "\n  step: "
                + str(self.seqs[0].signals.step.value)
                + "/"
                + str(self.seqs[0].signals.step_len.value)
            )
            ret += "\n  [tracks]"
            for x, seq in enumerate(self.seqs):
                ret += (
                    "\n    "
                    + str(x)
                    + " [  "
                    + "".join(["X  " if x > 0 else ".  " for x in seq.table[1:]])
                    + "]"
                )
            return ret
    
        @property
        def bpm(self):
            return self._bpm
    
        @bpm.setter
        def bpm(self, bpm):
            for seq in self.seqs:
                seq.signals.bpm.value = bpm
            self._bpm = bpm
    
        def trigger_start(self, track, step):
            a = self.seqs[track].table
            a[step + 1] = 32767
            self.seqs[track].table = a
    
        def trigger_stop(self, track, step):
            a = self.seqs[track].table
            a[step + 1] = 0
            self.seqs[track].table = a
    
        def trigger_state(self, track, step):
            a = self.seqs[track].table
            return a[step + 1]
    
        def trigger_toggle(self, track, step):
            if self.trigger_state(track, step) == 0:
                self.trigger_start(track, step)
            else:
                self.trigger_stop(track, step)
    
        @property
        def step(self):
            return self.seqs[0].signals.step
    
    
    class fuzz(_Patch):
        def __init__(self, chan):
            self.buds = _PatchBudList()
            self.signals = _PatchSignalList()
            self.buds.dist = chan.new(bl00mbox.plugins.distortion)
            self.signals.input = self.buds.dist.signals.input
            self.signals.output = self.buds.dist.signals.output
            self._intensity = 2
            self._volume = 32767
            self._gate = 0
    
        @property
        def intensity(self):
            return self._intensity
    
        @intensity.setter
        def intensity(self, val):
            self._intensity = val
            self._update_table()
    
        @property
        def volume(self):
            return self._volume
    
        @volume.setter
        def volume(self, val):
            self._volume = val
            self._update_table()
    
        @property
        def gate(self):
            return self._gate
    
        @gate.setter
        def gate(self, val):
            self._gate = val
            self._update_table()
    
        def _update_table(self):
            table = list(range(129))
            for num in table:
                if num < 64:
                    ret = num / 64  # scale to [0..1[ range
                    ret = ret**self._intensity
                    if ret > 1:
                        ret = 1
                    table[num] = int(self._volume * (ret - 1))
                else:
                    ret = (128 - num) / 64  # scale to [0..1] range
                    ret = ret**self._intensity
                    table[num] = int(self._volume * (1 - ret))
            gate = self.gate >> 9
            for i in range(64 - gate, 64 + gate):
                table[i] = 0
            self.buds.dist.table = table
    
    
    class karplus_strong(_Patch):
        def __init__(self, chan):
            self.buds = _PatchBudList()
            self.signals = _PatchSignalList()
    
            self.buds.noise = chan.new_bud(bl00mbox.plugins.noise_burst)
            self.buds.noise.signals.length = 25
    
            self.buds.flanger = chan.new_bud(bl00mbox.plugins.flanger)
    
            self.buds.flanger.signals.resonance = 32500
            self.buds.flanger.signals.manual.tone = "A2"
    
            self.buds.flanger.signals.input = self.buds.noise.signals.output
    
            self.signals.trigger = self.buds.noise.signals.trigger
            self.signals.pitch = self.buds.flanger.signals.manual
            self.signals.output = self.buds.flanger.signals.output
    
            self.signals.level = self.buds.flanger.signals.level
            self.decay = 1000
    
        @property
        def decay(self):
            return self._decay
    
        @decay.setter
        def decay(self, val):
            tone = self.buds.flanger.signals.manual.tone
            loss = (50 * (2 ** (-tone / 12))) // (val / 1000)
            if loss < 2:
                loss = 2
            self.buds.flanger.signals.resonance = 32767 - loss
            self._decay = val