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 __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
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()
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()