Exemple #1
0
class MainWidget3(BaseWidget):
    def __init__(self):
        super(MainWidget3, self).__init__()

        # create a clock and TempoMap
        self.clock = Clock()
        self.tempo = SimpleTempoMap(120)

        # create a Scheduler
        self.sched = Scheduler(self.clock, self.tempo)

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)

        # to see accumulated output:
        self.output_text = ''

    def on_key_down(self, keycode, modifiers):
        if keycode[1] == 'c':
            self.clock.toggle()

        if keycode[1] == 'a':
            now = self.sched.get_tick()
            later = now + (2 * kTicksPerQuarter)
            self.output_text += "now={}. post at tick={}\n".format(now, later)
            self.cmd = self.sched.post_at_tick(self._do_it, later, 'hello')

        if keycode[1] == 'b':
            self.sched.remove(self.cmd)

    def _do_it(self, tick, msg):
        self.output_text += "{} (at {})\n".format(msg, tick)

    def on_update(self):
        # scheduler gets called every frame to process events
        self.sched.on_update()
        self.label.text = self.sched.now_str() + '\n'
        self.label.text += 'c: toggle clock\n'
        self.label.text += 'a: post event\n'
        self.label.text += 'b: remove event\n'
        self.label.text += self.output_text
Exemple #2
0
class DataPlayer(object):
    """Plays a steady click every beat.
    """
    def __init__(self, callback=None):
        super(DataPlayer, self).__init__()
        self.sched = Scheduler(Clock(),
                               tempo_map=[(0, 0),
                                          (100000000000,
                                           100000000000 / 60 * 480)])
        self.beat_len = kTicksPerQuarter
        self.on_cmd = None
        self.off_cmd = None
        self.playing = False
        self.callback = None
        self.barData = None

    def start(self):
        if self.playing:
            return
        self.playing = True
        now = self.sched.get_tick()
        next_beat = quantize_tick_up(now, self.beat_len)
        self.on_cmd = self.sched.post_at_tick(self.tick, next_beat)

    def stop(self):
        if not self.playing:
            return
        self.playing = False
        if self.off_cmd:
            self.off_cmd.execute()
        self.sched.remove(self.on_cmd)
        self.sched.remove(self.off_cmd)
        self.on_cmd = None
        self.off_cmd = None

    # def set_bar(self, bar_data):
    #     self.barData = bar_data

    def toggle(self):
        if self.playing:
            self.stop()
        else:
            self.start()

    def tick(self, tick, ignore):
        next_beat = tick + self.beat_len
        self.on_cmd = self.sched.post_at_tick(self.tick, next_beat)


# class ScoreScreen(BaseWidget):
#     def __init__(self, scoreCard=ScoreCard(), callBack=None):
#         super(ScoreScreen, self).__init__()
#         w = Window.width//3
#         buttonSize = (w, w//3)
#         buttonAnchor = (3*Window.width//4, Window.height//4)
#         self.scoreCard = scoreCard
#         titleString= "Score Card"
#         title = Rectangle(pos=(Window.width//4, 3*Window.height//4), size=(2*Window.width//4, Window.height//5))
#         label = CoreLabel(text=titleString, font_size=56)
#         label.refresh()
#         text = label.texture
#         title.texture = text
#         self.objects = AnimGroup()
#         self.cards = self.generateTiles(self.scoreCard.getAllStrings())
#         self.canvas.add(Rectangle(size=(Window.width,Window.height)))
#         self.canvas.add(self.objects)
#         self.canvas.add(Color(*(.05,.28,.1)))
#         self.canvas.add(title)
#         [self.objects.add(card) for card in self.cards]
#         print('ScoreScreen Initialized')

#     def generateTiles(self, scoreStrings):
#         print(scoreStrings)
#         xa,ya = (10,0)
#         x = xa
#         y = ya
#         padding = 10
#         tile = Card(scoreStrings[0])

#         w,h = tile.getSize()
#         outputs = [tile]
#         for i in range(1, len(scoreStrings)):
#             if i % 5 == 0:
#                 y += h + padding
#                 x = xa - w- padding
#             x += w + padding
#             outputs.append(Card(scoreStrings[i], pos=(x,y), size=(w,h)))
#         return outputs

#     def on_update(self):
#         self.objects.on_update()
#         # print('homescreenUpdate')

#     def on_key_down(self, keycode, modifiers):
#         pass

# run(ScoreScreen)
Exemple #3
0
class Ticker(object):
    ''' 
    Maps beat patterns to ticks (time stamps) and plays the call of the call and response (if enabled)
    This class assumes quarter notes as beats.
    becase every loop in this game is 4 measures, we will assume a loop to last 16 beats.  (4/4)
    '''
    bpm = 400
    numRepeats = 3
    measuresPerCall = 1
    channel = 0
    vel = 80
    playQueues = 1
    noteDuration = 1
    nowBarHeight = Window.height // 2
    endBarTicks = kTicksPerQuarter * .5
    barLenTicks = kTicksPerQuarter * 4 + endBarTicks
    gemRadius = 100
    padding = gemRadius + 50

    def __init__(self, songPattern, key, clock):
        self.slack_timout = beats_to_time(.5, self.bpm)
        self.gems, self.bars = self._initialize_bars(songPattern, key)
        self.synth = Synth('../bank/FluidR3_GM.sf2')
        totalBeats = self.measuresPerCall * self.numRepeats * len(
            self.bars) * 4
        totalTime = beats_to_time(totalBeats, self.bpm)
        totalOffsetTicks = self.endBarTicks * totalBeats / 4
        totalTicks = totalBeats / 4 * self.barLenTicks
        data = [(0, 0),
                ((totalTime + ticks_to_time(totalOffsetTicks, self.bpm)) * 2,
                 totalTicks * 2)]
        self.tempo = TempoMap(data=data)
        self.num_bars = len(data)
        self.scheduler = Scheduler(clock, self.tempo)
        self.increment_bar = None
        self.catch_passes = None
        self.on_commands = []  # commands for a bar of call and response
        self.off_commands = []
        self.active_gems = []
        self.gem_commands = []
        self.bar_tick = 0
        self.bar_index = 0
        print(songPattern)

    def reset(self):
        #TODO
        for i in range(len(self.num_bars)):
            self.clear_bar(i)
        self.bar_index = 0

    def create_bar(self, barIndex):
        self.bar_tick = quantize_tick_up(self.scheduler.get_tick())
        self.active_gems = self.gems[barIndex]
        # print(list(map(lambda x: x.beat, self.active_gems)))
        # [gem.activate() for gem in self.active_gems]
        self._initializeBarAudio(barIndex)
        self._initializeBarGems(barIndex)
        # self.increment_bar

    def clear_bar(self, barIndex):
        self._clearBarAudio(barIndex)
        self._clearBarGems()

    def getRelativeTick(self):
        tick = quantize_tick_up(self.scheduler.get_tick())
        tick = (tick - self.bar_tick) % self.barLenTicks
        return tick

    def getTick(self):
        return quantize_tick_up(self.scheduler.get_tick())

    def getTargetGem(self):
        tick = self.getRelativeTick()
        beatApprox = (tick / self.barLenTicks) * 4
        #find gem by tick
        targetGem = None
        minDist = 9999999999
        for gem in self.active_gems:
            if gem.hit or gem.miss:
                # print("skipping hit gem (target) ", tick)
                continue
            gemDist = min(abs(gem.beat - beatApprox),
                          abs(beatApprox - gem.beat))
            if gemDist < minDist:
                minDist = gemDist
                targetGem = gem
        # print("minimum dist: ", minDist)
        # print("targetGem: ", gem.beat)
        # print("beat approx: ", beatApprox)
        return targetGem

    def on_update(self):
        self.scheduler.on_update()
        tick = self.getTick()
        ticksEllapsed = (tick - self.bar_tick) % (self.barLenTicks * 4)
        if ticksEllapsed <= self.barLenTicks:
            return "call"
        elif ticksEllapsed <= self.numRepeats * self.barLenTicks:
            return "response"
        else:
            # print("tick %f, ticksEll %f, barTick %f, barLen %f " % (tick, ticksEllapsed, self.bar_tick, self.barLenTicks))
            print('nextStatus')
            return "next"

    def bars_remaining(self):
        tick = self.getTick()
        ticksEllapsed = (tick - self.bar_tick) % (self.barLenTicks * 4)
        barNum = round((self.numRepeats * self.barLenTicks - ticksEllapsed) /
                       self.barLenTicks)
        barsRemaining = np.clip(self.numRepeats - barNum - 1, 0,
                                self.numRepeats - 1)
        return barsRemaining

    def _initialize_bars(self, pattern, key):
        gem_bars = []
        chord_bars = []

        for bar in pattern:
            numGems = len(bar)
            assert numGems > 1
            w = (Window.width) // 5
            x = self.padding
            y = self.nowBarHeight
            chords_and_ticks = []
            gems = []
            for b in bar:
                assert b[1] <= self.measuresPerCall * 4 and b[1] > 0
                chord = key.generateChord(b[0])
                chords_and_ticks.append((chord, b[1]))
                x = w * b[1]
                gem = Gem(chord, (x, y), self.gemRadius, self.slack_timout,
                          b[1])
                gems.append(gem)

            chord_bars.append(chords_and_ticks)
            gem_bars.append(gems)
        return gem_bars, chord_bars

    def _initializeBarAudio(self, barIndex):
        bar_tick = int(self.bar_tick)
        bar = self.bars[barIndex]
        # print(self.bar_tick)
        assert self.numRepeats >= self.playQueues
        for i in range(self.playQueues):
            for chord, beat in bar:
                tick = bar_tick + beat * kTicksPerQuarter
                # print('audio ', tick)
                self.on_commands.append(
                    self.scheduler.post_at_tick(self._playChord, tick, chord))
                self.off_commands.append(
                    self.scheduler.post_at_tick(
                        self._endChord,
                        tick + kTicksPerQuarter * self.noteDuration, chord))
            bar_tick += self.barLenTicks

    def _clearBarAudio(self, barIndex):
        for c in self.on_commands:
            self.scheduler.remove(c)
        for c in self.off_commands:
            self.scheduler.remove(c)
            c.execute()

    def _initializeBarGems(self, barIndex):
        slackWinOffset = quantize_tick_up(
            float(self.slack_timout) / 2 * kTicksPerQuarter)
        bar_tick = int(self.bar_tick)
        bar = self.gems[barIndex]
        for i in range(self.numRepeats):
            for gem in bar:
                tick = bar_tick + gem.beat * kTicksPerQuarter
                if i > 0:
                    self.gem_commands.append(
                        self.scheduler.post_at_tick(self._startGemTimer,
                                                    tick - slackWinOffset,
                                                    gem))
                    ticks_to_time(tick - slackWinOffset, self.bpm)
            bar_tick += self.barLenTicks
            self.gem_commands.append(
                self.scheduler.post_at_tick(self._onCompleteMeasure, bar_tick))

    def _refreshBarGems(self):
        for gem in self.active_gems:
            gem.on_reset()
            # gem.activate()

    def _clearBarGems(self):
        for gem in self.active_gems:
            # pass
            gem.exit()

    def _onCompleteMeasure(self, tick, temp=None):
        allHit = True
        for gem in self.active_gems:
            allHit = allHit and gem.hit
        if allHit and not self.on_update() == "call":
            self.increment_bar(perfect=allHit)
            print('increment bar')
        else:
            print("measure over, resetting gems - %f" % self.getRelativeTick())
            self.catch_passes(True)
            self._refreshBarGems()

    def _startGemTimer(self, tick, gem):
        ''' starts the gem timer'''
        # print("start gem timer %f " % self.getRelativeTick())
        if not gem.hit:
            gem.activate()

    def _playChord(self, tick, chord):
        for note in chord._getMidiTones():
            self.synth.noteon(self.channel, note, self.vel)

    def _endChord(self, tick, chord):
        for note in chord._getMidiTones():
            self.synth.noteoff(self.channel, note)

    def initialize_callbacks(self, increment, catch_passes):
        self.increment_bar = increment
        self.catch_passes = catch_passes