Example #1
0
    def __init__(self):
        self.boat = boat.BareBoat()
        self.gui_file = "../data/computer-gui.xml"
        super(ComputerControlPanel, self).__init__()

        self.messages = self.builder.get_object("messages")
        self.command_line = self.builder.get_object("command")
        self.rudder_adjustment = self.builder.get_object("rudder_adjustment")
        self.sail_adjustment = self.builder.get_object("sail_winch_adjustment")
        self.logging_adjustment = self.builder.get_object("logging_interval_adjustment")
        self.remote_uri_dialogue = self.builder.get_object("remote_boat_win_dialogue")
        self.remote_ip_widget = self.builder.get_object("remote_ip")
        self.remote_port_widget = self.builder.get_object("remote_port")
        self.about_dialogue = self.builder.get_object("about_dialogue")

        # The following bit replace the placeholder drawing area with the scene
        tmp = self.builder.get_object("drawingarea")
        tmp.destroy()
        self.scene = Scene(self.boat)
        box = self.builder.get_object("frame1")
        box.add(self.scene)

        gobject.timeout_add(10, self.serial_monitor)
        gobject.timeout_add(30, self.scene.redraw)
        self.on_ms_radio_toggled(None) # Initialise the values

        # Other varaibles
        self.logging_mode = False
        self.nm = None

        self.window.resize(900, 640)
        self.window.show_all()
Example #2
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
Example #3
0
class ComputerControlPanel(GeneralControlPanel):

    '''
    Provide the visual environment for interacting with the boat from the PC.
    '''

    def __init__(self):
        self.boat = boat.BareBoat()
        self.gui_file = "../data/computer-gui.xml"
        super(ComputerControlPanel, self).__init__()

        self.messages = self.builder.get_object("messages")
        self.command_line = self.builder.get_object("command")
        self.rudder_adjustment = self.builder.get_object("rudder_adjustment")
        self.sail_adjustment = self.builder.get_object("sail_winch_adjustment")
        self.logging_adjustment = self.builder.get_object("logging_interval_adjustment")
        self.remote_uri_dialogue = self.builder.get_object("remote_boat_win_dialogue")
        self.remote_ip_widget = self.builder.get_object("remote_ip")
        self.remote_port_widget = self.builder.get_object("remote_port")
        self.about_dialogue = self.builder.get_object("about_dialogue")

        # The following bit replace the placeholder drawing area with the scene
        tmp = self.builder.get_object("drawingarea")
        tmp.destroy()
        self.scene = Scene(self.boat)
        box = self.builder.get_object("frame1")
        box.add(self.scene)

        gobject.timeout_add(10, self.serial_monitor)
        gobject.timeout_add(30, self.scene.redraw)
        self.on_ms_radio_toggled(None) # Initialise the values

        # Other varaibles
        self.logging_mode = False
        self.nm = None

        self.window.resize(900, 640)
        self.window.show_all()

    def serial_monitor(self):
        msg = self.boat.poll_message()
        if msg != None and msg[0] != '!':
            self.messages.set_text(str(msg))
            if self.debug_mode:
                print ">>> ", msg
        if self.boat.pilot_mode != COMPUTER:   # Avoid infinite loop
            self.sail_adjustment.set_value(self.boat.sail_position)
            self.rudder_adjustment.set_value(self.boat.rudder_position)
        if self.logging_mode == True:
            self.do_log()
        if self.nm:
            self.nm.update_values()
        return True    #Necessary to keep it being scheduled by GObject

    def on_command_button_clicked(self, widget):
        self.boat.send_command(self.command_line.get_text())

    def on_set_log_speed_button_clicked(self, widget):
        tmp = self.logging_adjustment
        self.boat.send_command(SET_LOG_INTERVAL, int(tmp.value*tmp.multiplier))

    def on_stop_logging_button_clicked(self, widget):
        self.boat.send_command(SET_LOG_INTERVAL, 0)

    def on_ms_radio_toggled(self, widget):
        a = self.logging_adjustment
        a.value          = 100
        a.lower          = 100
        a.upper          = 1000
        a.step_increment = 50
        a.multiplier      = -1

    def on_s_radio_toggled(self, widget):
        a = self.logging_adjustment
        a.value          = 1
        a.lower          = 1
        a.upper          = 60
        a.step_increment = 1
        a.multiplier      = 1

    def on_m_radio_toggled(self, widget):
        a = self.logging_adjustment
        a.value          = 1
        a.lower          = 1
        a.upper          = 60
        a.step_increment = 1
        a.multiplier     = 1000

    def on_rc_button_toggled(self, widget):
        self.boat.send_command(SET_PILOT_MODE, RC)

    def on_autopilot_button_toggled(self, widget):
        self.boat.send_command(SET_PILOT_MODE, AUTO)

    def on_computer_pilot_button_toggled(self, widget):
        self.boat.send_command(SET_PILOT_MODE, COMPUTER)

    def on_off_pilot_button_toggled(self, widget):
        self.boat.send_command(SET_PILOT_MODE, OFF)

    def on_sail_winch_adjustment_value_changed(self, widget):
        if self.boat.pilot_mode != COMPUTER:
            return # Avoid an infinite loop
        self.boat.send_command(SET_SAIL, widget.get_value())

    def on_rudder_adjustment_value_changed(self, widget):
        if self.boat.pilot_mode != COMPUTER:
            return # Avoid an infinite loop
        self.boat.send_command(SET_RUDDER, widget.get_value())

    def on_logg_on_off_button_toggled(self, widget):
        state = widget.get_active()
        self.logging_mode = state
        widget.set_label("Logging in ON" if state else "Logging is OFF")

    def on_connect_remote_button_clicked(self, widget):
        if self.remote_ip_widget.get_text() == '':
            self.remote_ip_widget.set_text('192.168.1.35')
        if self.remote_port_widget.get_text() == '':
            self.remote_port_widget.set_text('5000')
        self.remote_uri_dialogue.show()

    def on_remote_boat_win_dialogue_delete_event(self, widget):
        widget.hide_on_delete()
        return True

    def on_boat_uri_button_clicked(self, widget):
        host = self.remote_ip_widget.get_text()
        port = int(self.remote_port_widget.get_text())
        try:
            remote_boat = boat.RemoteBoat((host, port))
        except Exception as e:
            print "Failed to connect: ", e
        else:
            self.boat = remote_boat
            self.remote_uri_dialogue.hide()
            self.scene.change_boat(self.boat)

    def on_disconnect_menu_item_activate(self, widget):
        print "disconnect"

    def on_log_activate_item(self, widget):
        print "log"

    def on_wifi_activate_item(self, widget):
        print "wifi"

    def on_serial_activate_item(self, widget):
        print "serial"

    def on_about_menu_item_activate(self, widget):
        self.about_dialogue.show()

    def on_about_dialogue_delete_event(self, widget):
        self.about_dialogue.hide()
        return True

    def on_about_dialogue_response(self, widget):
        self.about_dialogue.hide()

    def on_numeric_monitor_toggled(self, widget):
        if widget.get_active():
            if self.nm == None:
                self.nm = NumericMonitor(self.boat, widget)
            else:
                self.nm.window.show_all()
        else:
            self.nm.window.hide()

    def on_debug_mode_toggled(self, widget):
        self.debug_mode = widget.get_active()
Example #4
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()