Ejemplo n.º 1
0
class MainWidget1(BaseWidget) :
    def __init__(self):
        super(MainWidget1, 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) )

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

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

        if keycode[1] == 'a':
            self.arpeg.start()

        pitches = lookup(keycode[1], 'qwe', ((60, 64, 67, 72), (55, 59, 62, 65, 67, 71), (60, 65, 69)))
        if pitches:
            self.arpeg.set_pitches(pitches)

        rhythm = lookup(keycode[1], 'uiop', ((120, 1), (160, 1), (240, 0.75), (480, 0.25)))
        if rhythm:
            self.arpeg.set_rhythm(*rhythm)

        direction = lookup(keycode[1], '123', ('up', 'down', 'updown'))
        if direction:
            self.arpeg.set_direction(direction)

    def on_key_up(self, keycode):
        if keycode[1] == 'a':
            self.arpeg.stop()

    def on_update(self) :
        self.audio.on_update()
        self.label.text = self.sched.now_str() + '\n'
        self.label.text += 'tempo:%d\n' % self.tempo_map.get_tempo()
        self.label.text += 'm: toggle Metronome\n'
        self.label.text += 'a: Enable Arpeggiator\n'
        self.label.text += 'q w e: Changes pitches\n'
        self.label.text += 'u i o p: Change Rhythm\n'
        self.label.text += '1 2 3: Change Direction\n'
Ejemplo n.º 2
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.º 3
0
class MainWidget4(BaseWidget):
    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)

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

        if keycode[1] == 'm':
            self.metro.toggle()

        bpm_adj = lookup(keycode[1], ('up', 'down'), (10, -10))
        if bpm_adj:
            new_tempo = self.tempo_map.get_tempo() + bpm_adj
            self.tempo_map.set_tempo(new_tempo, self.sched.get_time())

    def on_update(self):
        # scheduler and audio get poked every frame
        self.sched.on_update()
        self.audio.on_update()

        bpm = self.tempo_map.get_tempo()

        self.label.text = self.sched.now_str() + '\n'
        self.label.text += 'Metronome:' + ("ON" if self.metro.playing else
                                           "OFF") + '\n'
        self.label.text += 'tempo:{}\n'.format(bpm)
        self.label.text += 'm: toggle Metronome\n'
        self.label.text += 'up/down: change speed\n'
Ejemplo n.º 4
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.º 5
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.º 6
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.º 7
0
class MainWidget5(BaseWidget):
    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)

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

        bpm_adj = lookup(keycode[1], ('up', 'down'), (10, -10))
        if bpm_adj:
            new_tempo = self.tempo_map.get_tempo() + bpm_adj
            self.tempo_map.set_tempo(new_tempo, self.sched.get_time())

    def on_update(self):
        self.audio.on_update()
        bpm = self.tempo_map.get_tempo()

        self.label.text = self.sched.now_str() + '\n'
        self.label.text += 'tempo:{}\n'.format(bpm)
        self.label.text += 'm: toggle Metronome\n'
        self.label.text += 'up/down: change speed\n'
Ejemplo n.º 8
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.º 9
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.º 10
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.º 11
0
    def __init__(self):
        super(IntroScreen, self).__init__()
        self.genre_popup = CheckboxPopup(self.genre_callback, "GENRE",
                                         GENRE_CHECKBOXES)
        self.volume_popup = VolumePopup(self.slider_callback)
        self.record_popup = RecordPopup(self.init_recording,
                                        self.toggle_playing)
        self.instruments_popup = CheckboxPopup(self.instrument_callback,
                                               "INSTRUMENTS",
                                               INSTRUMENT_CHECKBOXES)
        self.storage_popup = StoragePopup(self.get_live_wave,
                                          self.set_live_wave)
        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.playing = False
        self.recording = False
        self.cmd = None

        self.scene = Scene()
        self.add_widget(self.scene)
        self.scene.foreground.radio.set_callback(self.genre_popup.open)
        self.scene.foreground.amp.set_callback(self.volume_popup.open)
        self.scene.foreground.mic.set_callback(self.record_popup.open)
        self.scene.foreground.guitar.set_callback(self.instruments_popup.open)
        self.scene.foreground.storage.set_callback(self.storage_popup.open)

        self.cur_pitch = 0
        self.midi_notes = None

        self.bass = [((40, 60), (0, 0)), ((43, 64), (0, 42)),
                     ((28, 48), (0, 33))]
        self.tenor = [((52, 69), (0, 0)), ((52, 69), (0, 41)),
                      ((45, 64), (0, 26))]
        self.alto = [((57, 77), (0, 0)), ((60, 79), (0, 40)),
                     ((52, 72), (0, 29)), ((67, 86), (0, 73))]
        self.instruments = [self.bass, self.tenor, self.alto]
        self.genre = 'pop'

        self.indices = [0, 0, 0]

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

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)
        self.metro = Metronome(self.sched, self.synth)
        self.start_tick = None

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

        # Note Sequencers
        self.seq = [None, None, None]

        # live Generator
        self.live_wave = None

        # current .wav file
        self.current_wave_file = None
Ejemplo n.º 12
0
class IntroScreen(BaseWidget):
    image = "data/bedroom.jpg"

    def __init__(self):
        super(IntroScreen, self).__init__()
        self.genre_popup = CheckboxPopup(self.genre_callback, "GENRE",
                                         GENRE_CHECKBOXES)
        self.volume_popup = VolumePopup(self.slider_callback)
        self.record_popup = RecordPopup(self.init_recording,
                                        self.toggle_playing)
        self.instruments_popup = CheckboxPopup(self.instrument_callback,
                                               "INSTRUMENTS",
                                               INSTRUMENT_CHECKBOXES)
        self.storage_popup = StoragePopup(self.get_live_wave,
                                          self.set_live_wave)
        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.playing = False
        self.recording = False
        self.cmd = None

        self.scene = Scene()
        self.add_widget(self.scene)
        self.scene.foreground.radio.set_callback(self.genre_popup.open)
        self.scene.foreground.amp.set_callback(self.volume_popup.open)
        self.scene.foreground.mic.set_callback(self.record_popup.open)
        self.scene.foreground.guitar.set_callback(self.instruments_popup.open)
        self.scene.foreground.storage.set_callback(self.storage_popup.open)

        self.cur_pitch = 0
        self.midi_notes = None

        self.bass = [((40, 60), (0, 0)), ((43, 64), (0, 42)),
                     ((28, 48), (0, 33))]
        self.tenor = [((52, 69), (0, 0)), ((52, 69), (0, 41)),
                      ((45, 64), (0, 26))]
        self.alto = [((57, 77), (0, 0)), ((60, 79), (0, 40)),
                     ((52, 72), (0, 29)), ((67, 86), (0, 73))]
        self.instruments = [self.bass, self.tenor, self.alto]
        self.genre = 'pop'

        self.indices = [0, 0, 0]

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

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)
        self.metro = Metronome(self.sched, self.synth)
        self.start_tick = None

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

        # Note Sequencers
        self.seq = [None, None, None]

        # live Generator
        self.live_wave = None

        # current .wav file
        self.current_wave_file = None

    def genre_callback(self, value, label):
        self.genre = value
        if value == 'classical':
            self.instruments_popup.set_checkboxes(ORCHESTRA)
            self.indices = [1, 1, 1]
            self.instrument_callback(None, None)
        if value == 'pop':
            self.instruments_popup.set_checkboxes(POP)
            self.indices = [2, 2, 0]
            self.instrument_callback(None, None)

    def instrument_callback(self, value, label):
        if label == 'high voice':
            self.indices[2] = ['piano', 'violin', 'guitar',
                               'flute'].index(value)
        if label == 'mid voice':
            self.indices[1] = ['piano', 'viola', 'guitar'].index(value)
        if label == 'low voice':
            self.indices[0] = ['piano', 'cello', 'bass'].index(value)
        if self.live_wave is not None:
            for i in self.seq:
                i.stop()
                self.live_wave.reset()
                #reharmonize and update NoteSequencers
            duration_midi = harmony.harmonize(
                self.midi_notes,
                self.genre,
                brange=self.bass[self.indices[0]][0],
                trange=self.tenor[self.indices[1]][0],
                arange=self.alto[self.indices[2]][0])
            tempo = self.tempo_map.get_tempo()
            multiplier = 1 / 60 * tempo * 480
            converted_midi_duration = [[(i * multiplier, j) for i, j in k]
                                       for k in duration_midi]

            for i in range(3):
                self.seq[i] = NoteSequencer(
                    self.sched, self.synth, i + 1,
                    self.instruments[i][self.indices[i]][1],
                    converted_midi_duration[i + 1], self.scene.add_note_sprite,
                    True)
            if self.playing:
                self.play_recording(1)

    def slider_callback(self, voice, value):
        val = int(value)
        idx = ["bass", "tenor", "alto", "melody"].index(voice) + 1
        if idx < 4:
            self.synth.cc(idx, 7, val)
        else:
            if self.live_wave:
                self.live_wave.set_gain(val / 100)

    def on_update(self):
        self.audio.on_update()
        self.scene.on_update()

    def on_key_down(self, keycode, modifiers):
        if keycode[1] == 'm':
            self.metro.toggle()
        bpm_adj = lookup(keycode[1], ('up', 'down'), (10, -10))
        if bpm_adj and not self.playing and not self.recording:
            new_tempo = max(self.tempo_map.get_tempo() + bpm_adj, 30)
            self.tempo_map.set_tempo(new_tempo, self.sched.get_time())

    def receive_audio(self, frames, num_channels):
        assert (num_channels == 1)

        # Microphone volume level, take RMS, convert to dB.
        # display on meter and graph
        rms = np.sqrt(np.mean(frames**2))
        rms = np.clip(rms, 1e-10, 1)  # don't want log(0)
        db = 20 * np.log10(rms)  # convert from amplitude to decibels
        self.record_popup.mic_meter.set(db)
        self.record_popup.mic_graph.add_point(db)

        # pitch detection: get pitch and display on meter and graph
        self.cur_pitch = self.pitch.write(frames)
        self.record_popup.pitch_meter.set(self.cur_pitch)
        self.record_popup.pitch_graph.add_point(self.cur_pitch)

        # record audio
        self.recorder.add_audio(frames, num_channels)

    def init_recording(self):
        if not self.recording:
            self.start_tick = self.sched.get_tick()
        data = self.recorder.toggle()
        if not data:
            self.recording = True
            if self.live_wave is not None:
                try:
                    self.mixer.remove(self.live_wave)
                except:
                    pass
            for i in self.seq:
                if i is not None:
                    i.stop()
            self.playing = False
        else:
            self.recording = False
            stop_tick = self.sched.get_tick()
            wave_gen, filename, duration_midi = data
            self.current_wave_file = WaveFile(filename)
            #ignore short notes
            i = 0
            while i < len(duration_midi):
                if duration_midi[i][0] < 0.1:
                    duration_midi[i - 1] = (duration_midi[i][0] +
                                            duration_midi[i - 1][0],
                                            duration_midi[i - 1][1])
                    duration_midi.pop(i)
                else:
                    i += 1
            duration_midi[0] = (duration_midi[0][0] - .1, duration_midi[0][1])
            ticks = [(int(note[0] * 480 * self.tempo_map.get_tempo() / 60),
                      note[1]) for note in duration_midi]
            ticks[0] = (ticks[0])
            duration_midi = []
            tick_length = sum(i[0] for i in ticks)
            curr_beat = int(480 - self.start_tick % 480 +
                            .22 * 8 * self.tempo_map.get_tempo()) % 480
            ind = 0
            ticks_passed = 0
            while tick_length > 0:
                tot = 0
                times = {}
                while tot < curr_beat and ind < len(ticks):
                    left = ticks[ind][0] - ticks_passed
                    if left > curr_beat - tot:
                        ticks_passed += curr_beat - tot
                        if ticks[ind][1] in times:
                            times[ticks[ind][1]] += curr_beat - tot
                        else:
                            times[ticks[ind][1]] = curr_beat - tot
                        tot = curr_beat
                    else:
                        tot += left
                        ticks_passed = 0
                        if ticks[ind][1] in times:
                            times[ticks[ind][1]] += left
                        else:
                            times[ticks[ind][1]] = left
                        ind += 1
                big = 80
                note = 0
                print(times)
                for guy in times:
                    if times[guy] > big and guy != 0:
                        note = guy
                        big = times[guy]
                duration_midi.append(
                    (60 * curr_beat / 480 / self.tempo_map.get_tempo(), note))
                tick_length -= curr_beat
                curr_beat = min(480, tick_length)
            duration_midi = [(0.1, 0)] + duration_midi
            self.midi_notes = duration_midi
            #find harmonies
            self.live_wave = wave_gen
            good = False
            for i in duration_midi:
                if i[1] > 0:
                    good = True
                    break
            if good:
                duration_midi = harmony.harmonize(
                    duration_midi,
                    self.genre,
                    brange=self.bass[self.indices[0]][0],
                    trange=self.tenor[self.indices[1]][0],
                    arange=self.alto[self.indices[2]][0])
                #print([[i[1] for i in j] for j in duration_midi])

                # cheat to use SimpleTempoMap
                tempo = self.tempo_map.get_tempo()
                multiplier = 1 / 60 * tempo * 480
                converted_midi_duration = [[(i * multiplier, j) for i, j in k]
                                           for k in duration_midi]
                #make NoteSequencers
                for i in range(3):
                    self.seq[i] = NoteSequencer(
                        self.sched, self.synth, i + 1,
                        self.instruments[i][self.indices[i]][1],
                        converted_midi_duration[i + 1],
                        self.scene.add_note_sprite, True)

    def play_recording(self, tick):
        for i in self.seq:
            if i is not None:
                i.start()
        if self.live_wave:
            self.live_wave.play()
            if self.live_wave not in self.mixer.generators:
                self.mixer.add(self.live_wave)

    def start_playing(self):
        if self.playing:
            return
        self.metro.stop()
        self.playing = True

        now = self.sched.get_tick()
        next_beat = quantize_tick_up(now, kTicksPerQuarter * 4)
        self.cmd = self.sched.post_at_tick(self.play_recording, next_beat)

    def stop_playing(self):
        if not self.playing:
            return

        self.playing = False
        for i in self.seq:
            i.stop()
        self.live_wave.reset()

        self.sched.cancel(self.cmd)
        self.cmd = None

    def toggle_playing(self):
        print(self.playing)
        if self.playing:
            self.stop_playing()
        else:
            self.start_playing()

    def get_live_wave(self):
        if self.live_wave:
            return WaveGenerator(self.current_wave_file, True), self.seq.copy()

    def set_live_wave(self, new_live_wave, note_sequencers):
        if self.live_wave:
            if self.live_wave is not None:
                try:
                    self.mixer.remove(self.live_wave)
                except:
                    pass

            for i in self.seq:
                if i is not None:
                    i.stop()
            self.seq = note_sequencers
            for i in self.seq:
                if i is not None:
                    i.start()
            self.live_wave = new_live_wave
            self.mixer.add(self.live_wave)
            self.start_playing()