示例#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'
示例#2
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'
示例#3
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'
示例#4
0
文件: main.py 项目: quiche19/Vocagen
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()