Ejemplo n.º 1
0
	def __init__(self, sched):
		super(InstrumentManager, self).__init__()
		self.synth = Synth("data/FluidR3_GM.sf2")
		self.add_generator(self.synth)

		self.metro = Metronome(sched, self.synth)
		self.inst_count = 1

		self.instruments = []
Ejemplo n.º 2
0
class InstrumentManager(GameObject):

	def __init__(self, sched):
		super(InstrumentManager, self).__init__()
		self.synth = Synth("data/FluidR3_GM.sf2")
		self.add_generator(self.synth)

		self.metro = Metronome(sched, self.synth)
		self.inst_count = 1

		self.instruments = []


	# Adds instrument to manager. Each instrument is added to 
	# a new channel.
	def add(self, ins):
		self.inst_count += 1
		self.instruments.append(ins)
		ins.manager = self
		ins.channel = self.inst_count
		self.synth.program(self.inst_count, *ins.patch)

	def program(self, ins):
		self.synth.program(ins.channel, *ins.patch)

	def noteon(self, *args):
		self.synth.noteon(*args)

	def noteoff(self, *args):
		self.synth.noteoff(*args)
Ejemplo n.º 3
0
    def __init__(self):
        super(MainWidget, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # Note Sequencers
        self.seq1 = NoteSequencer(self.sched, self.synth, 1, (0, 65),
                                  kYesterday, False)
        self.seq2 = NoteSequencer(self.sched, self.synth, 2, (0, 52),
                                  kSomewhere, True)

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)
Ejemplo n.º 4
0
    def __init__(self,
                 notes,
                 bank=0,
                 preset=0,
                 loop=False,
                 simon_says=False,
                 bass_puzzle=False):
        super().__init__()
        self.audio = Audio(2)
        self.synth = Synth("./data/FluidR3_GM.sf2")

        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)
        self.sched.set_generator(self.synth)
        self.audio.set_generator(self.sched)

        self.notes = notes
        self.bank = bank
        self.preset = preset
        self.loop = loop
        self.simon_says = simon_says
        self.bass_puzzle = bass_puzzle

        self.note_seq = NoteSequencer(
            sched=self.sched,
            synth=self.synth,
            channel=1,
            program=(self.bank, self.preset),
            notes=self.notes,
            loop=self.loop,
        )
Ejemplo n.º 5
0
    def __init__(self):
        super(MainWidget1, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')
        self.audio.set_generator(self.synth)

        self.label = topleft_label()
        self.add_widget(self.label)

        cc_range = range(0, 128, 8)
        self.modifier = Modifier()
        self.modifier.add('a', "program", range(128),
                          lambda x: self.synth.program_change(0, x))
        self.modifier.add('s', "vibrato", cc_range,
                          lambda x: self.synth.cc(0, 1, x))
        self.modifier.add('d', "volume", cc_range,
                          lambda x: self.synth.cc(0, 7, x))
        self.modifier.add('f', "sustain", (0, 127),
                          lambda x: self.synth.cc(0, 64, x))
        self.modifier.add('z', "bend", range(-8192, 8192, 256),
                          lambda x: self.synth.pitch_bend(0, int(x)))
Ejemplo n.º 6
0
class MainWidget1(BaseWidget):
    def __init__(self):
        super(MainWidget1, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')
        self.audio.set_generator(self.synth)

        self.label = topleft_label()
        self.add_widget(self.label)

        cc_range = range(0, 128, 8)
        self.modifier = Modifier()
        self.modifier.add('a', "program", range(128),
                          lambda x: self.synth.program_change(0, x))
        self.modifier.add('s', "vibrato", cc_range,
                          lambda x: self.synth.cc(0, 1, x))
        self.modifier.add('d', "volume", cc_range,
                          lambda x: self.synth.cc(0, 7, x))
        self.modifier.add('f', "sustain", (0, 127),
                          lambda x: self.synth.cc(0, 64, x))
        self.modifier.add('z', "bend", range(-8192, 8192, 256),
                          lambda x: self.synth.pitch_bend(0, int(x)))

    def on_key_down(self, keycode, modifiers):
        self.modifier.on_key_down(keycode[1])

        pitch = lookup(keycode[1], kKeys, kPitches)
        if pitch:
            self.synth.noteon(0, pitch, 100)

    def on_key_up(self, keycode):
        self.modifier.on_key_up(keycode[1])

        pitch = lookup(keycode[1], kKeys, kPitches)
        if pitch:
            self.synth.noteoff(0, pitch)

    def on_update(self):
        self.audio.on_update()
        self.modifier.on_update()
        self.label.text = self.modifier.get_txt() + '\n'
Ejemplo n.º 7
0
 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)
Ejemplo n.º 8
0
    def __init__(self):
        super(MainWidget4, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')
        self.audio.set_generator(self.synth)

        # create clock, tempo_map, scheduler
        self.clock = Clock()
        self.tempo_map = SimpleTempoMap(120)
        self.sched = Scheduler(self.clock, self.tempo_map)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)
Ejemplo n.º 9
0
    def __init__(self):
        super(MainWidget2, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map  = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # create the arpeggiator:
        self.arpeg = Arpeggiator(self.sched, self.synth, channel = 1, program = (0,0) )
        self.arpeg.set_direction('updown')
        
        #size of the notes sent to the arpeggiator
        self.arpegSize = 3 
        #all of the notes this program can make. However, only self.arpegSize notes are sent to the arpegiator at a time
        self.allNotes = [50, 53, 55, 56, 57, 60, 62, 65, 67, 68, 69, 72, 74]

        self.lastPitchIndex = None
        self.lastPulseIndex = None

        self.noteLengths = [240, 210, 180, 150, 120, 90, 60]
        self.articulation = .75

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

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

        self.objects = AnimGroup()
        self.canvas.add(self.objects)

        self.add_lines()
Ejemplo n.º 10
0
    def __init__(self):
        super(MainWidget5, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)
Ejemplo n.º 11
0
    def __init__(self):
        super(MainWidget, self).__init__()

        self.writer = AudioWriter('song')
        self.audio = Audio(2, self.writer.add_audio)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(95*2)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # variables to store options
        self.transposition = 0
        self.style = None
        self.melody = None
        self.chords = None
        self.chord_option = None
        self.perc = None
        self.perc_option = None

        # variables to store screen options
        self.style_selection = StyleSelection(self.update_style_screen)    # screen index 0
        self.key_selection = KeySelection(self.update_key_screen)          # screen index 1
        self.chord_selection = None                                 # screen index 2
        self.perc_selection = None                                  # screen index 3
        self.melody_selection = None                                # screen index 4

        self.active_screen = self.style_selection
        self.screen_index = 0
        self.add_widget(self.active_screen)
Ejemplo n.º 12
0
    def __init__(self, norm, sandbox, mixer, client, client_id):
        self.norm = norm
        self.module_name = 'SoundBlock'
        self.sandbox = sandbox

        self.mixer = mixer
        self.tempo_map = SimpleTempoMap(bpm=60)
        self.sched = AudioScheduler(self.tempo_map)
        self.synth = Synth("data/FluidR3_GM.sf2")
        self.sched.set_generator(self.synth)
        self.mixer.add(self.sched)
        self.cmd = {}

        self.client = client
        self.cid = client_id
        self.instruments = {
            'piano': 1,
            'violin': 41,
            'trumpet': 57,
            'ocarina': 80,
            'choir': 53
        }
        self.inst_list = ['piano', 'violin', 'trumpet', 'ocarina', 'choir']
        self.drumkit = {
            'snare': 38,
            'crash': 49,
            'bass': 35,
            'hihat': 46,
            'triangle': 81
        }
        self.drum_list = ['snare', 'crash', 'bass', 'hihat', 'triangle']
        self.channel = 0
        self.drum_channel = len(self.inst_list)

        # set up the correct sound (program: bank and preset)
        # each instrument is on a different channel
        for index, inst in enumerate(self.inst_list):
            self.synth.program(index, 0, self.instruments[inst])

        for index, drum in enumerate(self.drum_list):
            self.synth.program(index + len(self.instruments), 128, 0)

        # many variables here are dicts because a user's module handler needs to keep track of
        # not just its own variables, but other users' variables as well! so we use dictionaries
        # with client ids as the keys.
        self.hold_point = {}
        self.hold_shape = {}

        # this variable is needed for when a user clicks on a soundblock in a touch_down event,
        # so that the corresponding touch_up event is skipped
        self.skip = {}

        self.color_dict = {
            'red': (201 / 255, 108 / 255, 130 / 255),
            'orange': (214 / 255, 152 / 255, 142 / 255),
            'yellow': (238 / 255, 234 / 255, 202 / 255),
            'green': (170 / 255, 220 / 255, 206 / 255),
            'teal': (159 / 255, 187 / 255, 208 / 255),
            'blue': (44 / 255, 85 / 255, 123 / 255),
            'turquoise': (50 / 255, 147 / 255, 140 / 255),
            'indigo': (46 / 255, 40 / 255, 90 / 255),
            'violet': (147 / 255, 127 / 255, 159 / 255),
            'pink': (199 / 255, 150 / 255, 170 / 255),
            'peach': (238 / 255, 142 / 255, 154 / 255),
            'magenta': (172 / 255, 69 / 255, 133 / 255),
            'grey': (140 / 255, 143 / 255, 148 / 255),
            'white': (239 / 255, 226 / 255, 222 / 255)
        }

        self.default_color = self.color_dict['violet']
        self.default_pitch = 60
        self.default_timbre = 'sine'
        self.default_instrument = 'piano'
        self.default_drum = 'snare'

        self.color = {}
        self.pitch = {}
        self.timbre = {}
        self.instrument = {}
        self.drum = {}

        self.display = False

        self.blocks = AnimGroup()
        self.sandbox.add(self.blocks)

        self.gui = BlockGUI(self.norm,
                            pos=self.norm.nt((50, 100)),
                            is_drum=False,
                            pitch_callback=self.update_pitch,
                            instrument_callback=self.update_instrument,
                            drum_callback=self.update_drum)

        self.delete_mode = {}
Ejemplo n.º 13
0
    def __init__(self):
        super(MainWidget3, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map  = SimpleTempoMap(104)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)        

        percNotes = [(480,35), (360,42), (120,35), (480,35), (480,42)]

        
        self.base1Notes = [(240,43), (240,43), (240,43), (120,47), (240,41), (240,41), (360,41), (120,40),
                      (360,41), (240,41), (240,41), (120,40), (120,36), (480,-1), (120,40), (240,41), (120,43)]

        self.base2Notes = [(120,-1), (120,45), (240,43), (120,-1), (240,43), (120,40), (480,43), (120,-1), (120,45), (120,45), (120,48),
                      (240,-1), (240,41), (120,-1), (240,41), (120,40), (480,41), (120,-1), (120,45), (120,45), (120,48),
                      (240,-1), (240,45), (120,-1), (240,45), (120,45), (480,45), (240,43), (120,-1), (120,45),
                      (240,-1), (240,45), (120,-1), (240,45), (120,45), (480,45), (120,-1), (120,45), (120,45), (120,48)]  
        
        self.baseNotes = self.base2Notes
        #[40, 41, 43, 45 48,]


        #changes / pitch sutff
        self.changes = [ (1920, [72, 74, 76, 79, 81, 84]),
                    (1920, [69, 72, 74, 81]),
                    (3840, [69, 72, 74, 76, 79, 81, 84])]

        self.changesIndex = 0
        self.curChanges = []
        self.selectSize = 2
        self.lastPitchIndex = None
        self.lastTouch = None


        #Note length stuff
        self.noteLengths = [480, 240, 120]
        self.articulation = 1
        self.lastPulseIndex = 0

        #Declare the players
        self.perc = NoteSequencer(self.sched, self.synth, 1, (128,0), percNotes)
        self.base1 = NoteSequencer(self.sched, self.synth, 2, (0,33), self.base1Notes, callback = self.graphic_callback)
        self.base2 = NoteSequencer(self.sched, self.synth, 2, (0,33), self.base2Notes, callback = self.graphic_callback)
        self.lead = Arpeggiator(self.sched, self.synth, channel = 3, program = (0,65), callback = self.graphic_callback)
        self.lead.set_direction('updown')
        #Start the non-interactive stuff
        now = self.sched.get_tick()
        next_beat = quantize_tick_up(now, 480)
        self.perc.toggle()
        self.base2.toggle()
        self.sched.post_at_tick(self._updateChanges, next_beat) #Update changes as music starts
        self.sched.post_at_tick(self._spawnCrossBar, next_beat)


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

        #Graphics stuff
        self.objects = AnimGroup()
        self.canvas.add(self.objects)
        #self.allNotes = [40, 41, 43, 45, 48, 900, 69, 72, 74, 76, 79, 81, 84]
        self.allNotes = [36, 40, 41, 43, 45, 47, 48, 900, 69, 72, 74, 76, 79, 81, 84]
Ejemplo n.º 14
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
Ejemplo n.º 15
0
    def __init__(self, level, notes, goal_values, gear_values, **kwargs):
        super(LevelEasyMediumScreen, self).__init__(**kwargs)

        # set up notes for the level
        self.notes = notes

        # set up gear values for the levels
        self.goal_values = goal_values

        # set up gear values for the levels
        self.gear_values = gear_values

        self.level = level

        # only turn on tutorial for level 1
        if self.level == 1:
            self.use_tutorial = True
            self.tutorial_screen = 'A'
            self.goal_play_status = None
            self.gear_play_status = None
            self.size_dim = min(Window.width / 6, Window.height / 6)
            self.tutorial_full_overlay = CRectangle(cpos=(Window.width / 2,
                                                          Window.height / 2),
                                                    csize=(Window.width,
                                                           Window.height))
            self.tutorial_options_overlay = Rectangle(
                pos=(0, 0),
                size=(Window.width, self.size_dim + Window.height / 25))
            self.tutorial_musicbox_overlay = Rectangle(
                pos=(Window.width // 2, self.size_dim + Window.height / 25),
                size=(Window.width / 2,
                      Window.height - (self.size_dim + Window.height / 25)))
            self.tutorial_gearbox_overlay = Rectangle(
                pos=(0, self.size_dim + Window.height / 25),
                size=(Window.width / 2,
                      Window.height - (self.size_dim + Window.height / 25)))
            self.skip_image = CoreImage('images/skip_tutorial.png')
            self.tutorial_skip_button = Rectangle(
                pos=(0.98 * Window.width -
                     (self.skip_image.width * self.size_dim / 300),
                     0.98 * Window.height -
                     self.skip_image.height * self.size_dim / 300),
                size=(self.skip_image.width * self.size_dim / 300,
                      self.skip_image.height * self.size_dim / 300),
                texture=self.skip_image.texture)
        else:
            self.use_tutorial = False

        ############################################
        ###              GOAL MUSIC              ###
        ############################################
        self.goal_audio = Audio(2)
        self.goal_synth = Synth('./data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.goal_tempo_map = SimpleTempoMap(120)
        self.goal_sched = AudioScheduler(self.goal_tempo_map)

        # connect scheduler into audio system
        self.goal_audio.set_generator(self.goal_sched)
        self.goal_sched.set_generator(self.goal_synth)

        # generate goal music
        self.goal_music = MusicPlayer(notes=self.notes,
                                      sched=self.goal_sched,
                                      synth=self.goal_synth,
                                      channel=1,
                                      tempo_map=self.goal_tempo_map)
        self.goal_music.update_tempo(self.goal_values[0])
        self.goal_music.update_instrument(self.goal_values[1])
        self.goal_music.update_pitch(self.goal_values[2])
        self.goal_music.update_volume(self.goal_values[3])

        self.goal_music_seq = self.goal_music.generate()

        ############################################
        ###              GEAR MUSIC              ###
        ############################################
        self.gear_audio = Audio(2)
        self.gear_synth = Synth('./data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.gear_tempo_map = SimpleTempoMap(120)
        self.gear_sched = AudioScheduler(self.gear_tempo_map)

        # connect scheduler into audio system
        self.gear_audio.set_generator(self.gear_sched)
        self.gear_sched.set_generator(self.gear_synth)

        # generate gear music
        self.gear_music = MusicPlayer(notes=self.notes,
                                      sched=self.gear_sched,
                                      synth=self.gear_synth,
                                      channel=1,
                                      tempo_map=self.gear_tempo_map)
        self.gear_music_seq = None

        ############################################
        ###       BACKGROUND UI COMPONENTS       ###
        ############################################
        self.gear_area = GearArea()
        self.canvas.add(self.gear_area)

        self.music_box_area = MusicBoxArea()
        self.canvas.add(self.music_box_area)

        self.options = LevelOptions(
            level=level,
            goal_music_seq=self.goal_music_seq,
            duration=self.goal_music.duration,
            edit_goal_play_status=self.edit_goal_play_status)
        self.canvas.add(self.options)

        self.label = Label(text=kwargs['name'],
                           font_name='./fonts/PassionOne-Regular',
                           color=(.165, .718, .792, 1))
        self.add_widget(self.label)

        ###########################################
        ###             GEAR LABELS             ###
        ###########################################
        self.tempo_label = Label(text='Tempo (bpm)',
                                 font_name='./fonts/PassionOne-Regular',
                                 color=(0.7254901960784313, 0.5529411764705883,
                                        0.8196078431372549, 1),
                                 center_x=(Window.width / 4),
                                 center_y=(Window.height / 5.25 * (0.5 + 0.5) +
                                           self.gear_area.position[1]),
                                 font_size=str(Window.width // 50) + 'sp')
        self.instrument_label = Label(
            text='Instrument',
            font_name='./fonts/PassionOne-Regular',
            color=(0.996078431372549, 0.8431372549019608, 0.4, 1),
            center_x=(Window.width / 4),
            center_y=(Window.height / 5.25 * (1.5 + 0.5) +
                      self.gear_area.position[1]),
            font_size=str(Window.width // 50) + 'sp')
        self.pitch_label = Label(text='Pitch (semitones)',
                                 font_name='./fonts/PassionOne-Regular',
                                 color=(1.0, 0.6509803921568628,
                                        0.09019607843137255, 1),
                                 center_x=(Window.width / 4),
                                 center_y=(Window.height / 5.25 * (2.5 + 0.5) +
                                           self.gear_area.position[1]),
                                 font_size=str(Window.width // 50) + 'sp')
        self.volume_label = Label(
            text='Volume',
            font_name='./fonts/PassionOne-Regular',
            color=(0.9254901960784314, 0.32941176470588235, 0.3176470588235294,
                   1),
            center_x=(Window.width / 4),
            center_y=(Window.height / 5.25 * (3.5 + 0.5) +
                      self.gear_area.position[1]),
            font_size=str(Window.width // 50) + 'sp')
        self.add_widget(self.volume_label)
        self.add_widget(self.pitch_label)
        self.add_widget(self.instrument_label)
        self.add_widget(self.tempo_label)

        ###########################################
        ###          GEAR CONSTRUCTION          ###
        ###########################################

        self.gears = []
        self.gear_centers = []
        self.gears_group = AnimGroup()
        self.canvas.add(self.gears_group)

        ###########################################
        ###                GEARS                ###
        ###########################################
        self.gear_storage_locations = []
        self.gear_music_locations = []
        self.gear_labels = []
        self.set_up_gears()

        ###########################################
        ###           PARTICLE EFFECT           ###
        ###########################################
        self.win_ps = ParticleSystem('particles/star_particle.pex')
        self.win_ps.emitter_x = Window.width / 2
        self.win_ps.emitter_y = Window.height / 2
        self.add_widget(self.win_ps)
        self.you_win_label = Label(text=' ',
                                   font_name='./fonts/PassionOne-Regular',
                                   color=(0.5843137254901961,
                                          0.796078431372549,
                                          0.37254901960784315, 1),
                                   center_x=Window.width / 2,
                                   center_y=Window.height / 2,
                                   font_size=str(Window.width // 10) + 'sp')
        self.add_widget(self.you_win_label)

        self.lose_ps = ParticleSystem('particles/lose_particle.pex')
        self.lose_ps.emitter_x = Window.width / 2
        self.lose_ps.emitter_y = Window.height / 2
        self.add_widget(self.lose_ps)
        self.you_lose_label = Label(text=' ',
                                    font_name='./fonts/PassionOne-Regular',
                                    color=(0.9254901960784314,
                                           0.32941176470588235,
                                           0.3176470588235294, 1),
                                    center_x=Window.width / 2,
                                    center_y=Window.height / 2,
                                    font_size=str(Window.width // 10) + 'sp')
        self.add_widget(self.you_lose_label)

        ###########################################
        ###            ERROR MESSAGE            ###
        ###########################################
        self.error_msg = Label(text=' ',
                               font_name='./fonts/PassionOne-Regular',
                               color=(0.9254901960784314, 0.32941176470588235,
                                      0.3176470588235294, 1),
                               center_x=Window.width / 2,
                               center_y=Window.height / 2,
                               font_size=str(Window.width // 20) + 'sp')
        self.add_widget(self.error_msg)

        # ###########################################
        # ###        ADD TUTORIAL OVERLAYS        ###
        # ###########################################
        if self.use_tutorial:
            self.canvas.add(Color(rgba=(0, 0, 0, 0.85)))
            self.canvas.add(self.tutorial_full_overlay)
            self.tutorial_label = Label(
                markup=True,
                text=
                "[font=./fonts/lato-bold]Welcome to the\n[/font] [font=./fonts/options-icons]|[/font] [font=./fonts/PassionOne-Regular]Play It By Gear Tutorial[/font] [font=./fonts/options-icons]|[/font] [font=./fonts/lato-bold]\n\nThe goal of this game is to make the \n goal song match the song you create by \nplacing the correct gears in a music box \n\n[/font] [font=./fonts/lato-light] (click to see the next \nstep of the tutorial)[/font]",
                color=(86 / 255, 189 / 255, 205 / 255, 1),
                center_x=Window.width / 2,
                center_y=Window.height / 2,
                font_size=str(Window.width // 40) + 'sp',
                halign='center')
            self.add_widget(self.tutorial_label)
            self.canvas.add(self.tutorial_skip_button)

        self.on_layout((Window.width, Window.height))
Ejemplo n.º 16
0
    def __init__(self):
        super(MainWidget, self).__init__()

        self.audio = Audio(2,
                           input_func=self.receive_audio,
                           num_input_channels=1)
        self.mixer = Mixer()
        self.audio.set_generator(self.mixer)
        self.pitch = PitchDetector()
        self.recorder = VoiceAudioWriter('data')

        self.info = topleft_label()
        self.add_widget(self.info)

        self.anim_group = AnimGroup()

        self.mic_meter = MeterDisplay((50, 25), 150, (-96, 0), (.1, .9, .3))
        self.mic_graph = GraphDisplay((110, 25), 150, 300, (-96, 0),
                                      (.1, .9, .3))

        self.pitch_meter = MeterDisplay((50, 200), 150, (30, 90), (.9, .1, .3))
        self.pitch_graph = GraphDisplay((110, 200), 150, 300, (30, 90),
                                        (.9, .1, .3))

        self.canvas.add(self.mic_meter)
        self.canvas.add(self.mic_graph)
        self.canvas.add(self.pitch_meter)
        self.canvas.add(self.pitch_graph)

        # Record button
        self.record_button = InteractiveImage()
        self.record_button.source = "../data/mic.png"
        self.record_button.x = 400
        self.record_button.y = 400
        self.record_button.size = (100, 100)
        self.record_button.set_callback(self.init_recording)
        self.add_widget(self.record_button)

        # Play button
        self.play_button = InteractiveImage()
        self.play_button.source = "../data/play.png"
        self.play_button.x = 600
        self.play_button.y = 400
        self.play_button.size = (100, 100)
        self.play_button.set_callback(self.play_recording)
        self.add_widget(self.play_button)

        self.canvas.add(self.anim_group)

        self.onset_disp = None
        self.onset_x = 0
        self.cur_pitch = 0

        # Note Scheduler
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.mixer.add(self.sched)
        self.sched.set_generator(self.synth)

        # Note Sequencers
        self.seq = []

        # live Generator
        self.live_wave = None
Ejemplo n.º 17
0
class SoundBlockHandler(object):
    """
    Handles user interaction and drawing of graphics before generating a SoundBlock.
    Also stores and updates all currently active SoundBlocks.
    """
    def __init__(self, norm, sandbox, mixer, client, client_id):
        self.norm = norm
        self.module_name = 'SoundBlock'
        self.sandbox = sandbox

        self.mixer = mixer
        self.tempo_map = SimpleTempoMap(bpm=60)
        self.sched = AudioScheduler(self.tempo_map)
        self.synth = Synth("data/FluidR3_GM.sf2")
        self.sched.set_generator(self.synth)
        self.mixer.add(self.sched)
        self.cmd = {}

        self.client = client
        self.cid = client_id
        self.instruments = {
            'piano': 1,
            'violin': 41,
            'trumpet': 57,
            'ocarina': 80,
            'choir': 53
        }
        self.inst_list = ['piano', 'violin', 'trumpet', 'ocarina', 'choir']
        self.drumkit = {
            'snare': 38,
            'crash': 49,
            'bass': 35,
            'hihat': 46,
            'triangle': 81
        }
        self.drum_list = ['snare', 'crash', 'bass', 'hihat', 'triangle']
        self.channel = 0
        self.drum_channel = len(self.inst_list)

        # set up the correct sound (program: bank and preset)
        # each instrument is on a different channel
        for index, inst in enumerate(self.inst_list):
            self.synth.program(index, 0, self.instruments[inst])

        for index, drum in enumerate(self.drum_list):
            self.synth.program(index + len(self.instruments), 128, 0)

        # many variables here are dicts because a user's module handler needs to keep track of
        # not just its own variables, but other users' variables as well! so we use dictionaries
        # with client ids as the keys.
        self.hold_point = {}
        self.hold_shape = {}

        # this variable is needed for when a user clicks on a soundblock in a touch_down event,
        # so that the corresponding touch_up event is skipped
        self.skip = {}

        self.color_dict = {
            'red': (201 / 255, 108 / 255, 130 / 255),
            'orange': (214 / 255, 152 / 255, 142 / 255),
            'yellow': (238 / 255, 234 / 255, 202 / 255),
            'green': (170 / 255, 220 / 255, 206 / 255),
            'teal': (159 / 255, 187 / 255, 208 / 255),
            'blue': (44 / 255, 85 / 255, 123 / 255),
            'turquoise': (50 / 255, 147 / 255, 140 / 255),
            'indigo': (46 / 255, 40 / 255, 90 / 255),
            'violet': (147 / 255, 127 / 255, 159 / 255),
            'pink': (199 / 255, 150 / 255, 170 / 255),
            'peach': (238 / 255, 142 / 255, 154 / 255),
            'magenta': (172 / 255, 69 / 255, 133 / 255),
            'grey': (140 / 255, 143 / 255, 148 / 255),
            'white': (239 / 255, 226 / 255, 222 / 255)
        }

        self.default_color = self.color_dict['violet']
        self.default_pitch = 60
        self.default_timbre = 'sine'
        self.default_instrument = 'piano'
        self.default_drum = 'snare'

        self.color = {}
        self.pitch = {}
        self.timbre = {}
        self.instrument = {}
        self.drum = {}

        self.display = False

        self.blocks = AnimGroup()
        self.sandbox.add(self.blocks)

        self.gui = BlockGUI(self.norm,
                            pos=self.norm.nt((50, 100)),
                            is_drum=False,
                            pitch_callback=self.update_pitch,
                            instrument_callback=self.update_instrument,
                            drum_callback=self.update_drum)

        self.delete_mode = {}

    def on_touch_down(self, cid, pos):
        if cid == self.cid:
            self.gui.on_touch_down(pos)

        if not self.sandbox.in_bounds(pos):
            return

        # when a block is clicked, flash and play a sound
        for block in self.blocks.objects:
            if in_bounds(pos, block.pos, block.size):
                if self.delete_mode[cid]:
                    self.blocks.objects.remove(block)
                    self.blocks.remove(block)
                    return

                block.flash()
                self.skip[cid] = True
                return  # don't start drawing a SoundBlock

        if self.delete_mode[cid]:
            return

        self.hold_point[cid] = pos
        self.hold_shape[cid] = Rectangle(pos=pos, size=(0, 0))

        self.sandbox.add(Color(1, 1, 1))
        self.sandbox.add(self.hold_shape[cid])

    def on_touch_move(self, cid, pos):
        if not self.sandbox.in_bounds(pos):
            return

        #determine which direction rectangle is being created in
        hold_point = self.hold_point[cid]
        size = self.calculate_size(hold_point, pos)
        bottom_left = pos

        #moving northeast
        if pos[0] > hold_point[0] and pos[1] > hold_point[1]:
            bottom_left = hold_point

        #moving southeast
        elif pos[0] > hold_point[0] and pos[1] < hold_point[1]:
            bottom_left = (hold_point[0], pos[1])

        #moving southwest
        elif pos[0] < hold_point[0] and pos[1] < hold_point[1]:
            bottom_left = pos

        #moving northwest
        elif pos[0] < hold_point[0] and pos[1] > hold_point[1]:
            bottom_left = (pos[0], hold_point[1])

        self.hold_shape[cid].pos = bottom_left
        self.hold_shape[cid].size = size

    def on_touch_up(self, cid, pos):
        if self.skip.get(cid):
            self.skip[cid] = False
            return

        if self.delete_mode[cid]:
            return

        if self.hold_shape.get(cid) not in self.sandbox:
            if not self.sandbox.in_bounds(pos):
                return

        bottom_left = self.hold_shape[cid].pos
        size = self.hold_shape[cid].size

        if size[0] <= 10 or size[1] <= 10:
            self.sandbox.remove(self.hold_shape[cid])
            return

        self.sandbox.remove(self.hold_shape[cid])

        pitch = self.pitch[cid]
        color = self.color[cid]
        instrument = self.instrument[cid]
        self.channel = self.inst_list.index(instrument)
        drum = self.drum[cid]
        self.drum_channel = self.drum_list.index(drum) + len(self.inst_list)

        if self.gui.is_drum:
            block = SoundBlock(self.norm, self.sandbox, bottom_left, size,
                               self.drum_channel, self.drumkit[drum], color,
                               self, self.sound)
        else:
            block = SoundBlock(self.norm, self.sandbox, bottom_left, size,
                               self.channel, pitch, color, self, self.sound)
        self.blocks.add(block)

    def on_key_down(self, cid, key):
        index = lookup(key, 'q2w3er5t6y7ui', range(13))
        if index is not None:
            if self.cid == cid:
                self.gui.ps.select(index)
        if key == '[':
            if cid == self.cid:
                self.gui.ps.left_press()
        if key == ']':
            if cid == self.cid:
                self.gui.ps.right_press()

        if key == 'v' and cid == self.cid:
            self.delete_mode[cid] = not self.delete_mode[cid]
            self.update_server_state(post=True)

        if key == 'up':
            if not self.gui.is_drum:
                self.gui.switch_module()

        if key == 'down':
            if self.gui.is_drum:
                self.gui.switch_module()

        if self.gui.is_drum:
            drum = lookup(key, 'asdfg',
                          ['snare', 'crash', 'bass', 'hihat', 'triangle'])
            if drum is not None:
                self.drum[cid] = drum
                if self.cid == cid:
                    self.drum_channel = self.drum_list.index(drum) + len(
                        self.inst_list)
                    self.gui.ds.select(drum)
        else:
            instrument = lookup(
                key, 'asdfg',
                ['piano', 'violin', 'trumpet', 'ocarina', 'choir'])
            if instrument is not None:
                self.instrument[cid] = instrument
                if self.cid == cid:
                    self.channel = self.inst_list.index(instrument)
                    self.gui.ints.select(
                        instrument)  # have the GUI update as well

    def display_controls(self):
        info = 'delete mode: {}\n'.format(self.delete_mode[self.cid])
        if self.gui.is_drum:
            info += 'drum: {}\n'.format(self.drum_list[self.drum_channel -
                                                       len(self.inst_list)])
        else:
            info += 'instrument: {}\n'.format(self.inst_list[self.channel])
        return info

    def on_update(self):
        self.blocks.on_update()
        self.gui.on_update(Window.mouse_pos)

    def update_server_state(self, post=False):
        """
        Update server state. If post is True, relay this updated state to all clients.
        """
        state = {
            'color': self.color,
            'pitch': self.pitch,
            'timbre': self.timbre,
            'instrument': self.instrument,
            'drum': self.drum,
            'delete_mode': self.delete_mode
        }
        data = {
            'module': self.module_name,
            'cid': self.cid,
            'state': state,
            'post': post
        }
        self.client.emit('update_state', data)

    def update_client_state(self, cid, state):
        """
        Update this handler's state.
        """
        if cid != self.cid:  # this client already updated its own state
            self.color = state['color']
            self.pitch = state['pitch']
            self.timbre = state['timbre']
            self.instrument = state['instrument']
            self.drum = state['drum']
            self.delete_mode = state['delete_mode']

    def sync_state(self, state):
        """
        Initial sync with the server's copy of module state.
        We don't sync with hold_shape, hold_point, and hold_line because those objects are not
        json-serializable and are short-term values anyway.
        """
        self.color = state['color']
        self.pitch = state['pitch']
        self.timbre = state['timbre']
        self.instrument = state['instrument']
        self.drum = state['drum']
        self.delete_mode = state['delete_mode']

        # after initial sync, add default values for this client
        self.color[self.cid] = self.default_color
        self.pitch[self.cid] = self.default_pitch
        self.timbre[self.cid] = self.default_timbre
        self.instrument[self.cid] = self.default_instrument
        self.drum[self.cid] = self.default_drum
        self.delete_mode[self.cid] = False

        self.skip[self.cid] = False

        # now that default values are set, we can display this module's info
        self.display = True

        # update server with these default values
        # post=True here because we want all other clients' states to update with this client's
        # default values.
        self.update_server_state(post=True)

    def sound(self, channel, pitch):
        """
        Play a sound with a given pitch on the given channel.
        """
        if self.cmd.get((channel, pitch)):
            self.sched.cancel(self.cmd[(channel, pitch)])
        self.synth.noteon(channel, pitch, 100)
        now = self.sched.get_tick()
        self.cmd[(channel,
                  pitch)] = self.sched.post_at_tick(self._noteoff, now + 240,
                                                    (channel, pitch))

    def update_pitch(self, color, pitch):
        """Update this client's color and pitch due to PitchSelect."""

        self.color[self.cid] = self.color_dict[color]
        self.pitch[self.cid] = pitch
        self.update_server_state(post=True)

    def update_instrument(self, instrument):
        """Update this client's instrument due to InstrumentSelect."""
        self.instrument[self.cid] = instrument
        self.channel = self.inst_list.index(instrument)
        self.update_server_state(post=True)

    def update_drum(self, drum):
        self.drum[self.cid] = drum
        self.drum_channel = self.drum_list.index(drum) + len(self.inst_list)
        self.update_server_state(post=True)

    def _noteoff(self, tick, args):
        channel, pitch = args
        self.synth.noteoff(channel, pitch)

    def calculate_size(self, corner, pos):
        x = abs(pos[0] - corner[0])
        y = abs(pos[1] - corner[1])
        return (x, y)

    def calculate_center(self, corner, size):
        c_x = corner[0] + (size[0] / 2)
        c_y = corner[1] + (size[1] / 2)
        return (c_x, c_y)