Exemplo n.º 1
0
class RecorderApp(QDialog):
    def __init__(self):
        super().__init__()
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        # variables
        self.emotion_set = (
            'Pleasure',
            'Joy',
            'Pride',
            'Amusement',
            'Interest',
            'Anger',
            'Hate',
            'Contempt',
            'Disgust',
            'Fear',
            'Disappointment',
            'Shame',
            'Regret',
            'Guilt',
            'Sadness',
            'Compassion',
            'Relief',
            'Admiration',
            'Love',
            'Contentment',
        )
        self.emotion_buttons = (
            self.ui.radioButtonEmotion1,
            self.ui.radioButtonEmotion2,
            self.ui.radioButtonEmotion3,
            self.ui.radioButtonEmotion4,
            self.ui.radioButtonEmotion5,
            self.ui.radioButtonEmotion6,
            self.ui.radioButtonEmotion7,
            self.ui.radioButtonEmotion8,
            self.ui.radioButtonEmotion9,
            self.ui.radioButtonEmotion10,
            self.ui.radioButtonEmotion11,
            self.ui.radioButtonEmotion12,
            self.ui.radioButtonEmotion13,
            self.ui.radioButtonEmotion14,
            self.ui.radioButtonEmotion15,
            self.ui.radioButtonEmotion16,
            self.ui.radioButtonEmotion17,
            self.ui.radioButtonEmotion18,
            self.ui.radioButtonEmotion19,
            self.ui.radioButtonEmotion20,
        )
        self.emotion_button_dict = dict(
            zip(self.emotion_set, self.emotion_buttons))
        self.dataset_path = ''
        self.file_path = ''
        self.name_confirmed = False
        self.emotion_selected = False
        self.is_recording = False
        self.ready_to_record = False
        # other settings
        self.ui.stopButton.setEnabled(False)
        self.ui.recordButton.setEnabled(False)
        self.ui.editButton.setEnabled(False)
        self.timer = QtCore.QTimer()
        self._reset_time()
        self._set_audio_device_box()
        self._set_midi_device_box()
        self._open_midi_device()
        for emotion in self.emotion_set:
            self.emotion_button_dict[emotion].setText(emotion)
        # messages
        self.ui.recordButton.clicked.connect(self.start_recording)
        self.ui.stopButton.clicked.connect(self.stop_recording)
        self.ui.browseButton.clicked.connect(self.open_file_dialog)
        self.timer.timeout.connect(self.timer_event)
        self.ui.confirmButton.clicked.connect(self.confirm_name)
        self.ui.editButton.clicked.connect(self.edit_name)
        for emotion_button in self.emotion_buttons:
            emotion_button.clicked.connect(self.select_emotion)
        self.ui.instrumentBox.currentIndexChanged.connect(
            self._update_phrase_numbers)
        self.ui.midiDeviceBox.currentIndexChanged.connect(
            self._open_midi_device)

    def keyPressEvent(self, QKeyEvent):
        if QKeyEvent.key() == QtCore.Qt.Key_Space and self.ready_to_record:
            if self.ui.recordButton.isEnabled():
                self.ui.recordButton.clicked.emit()
            elif self.ui.stopButton.isEnabled():
                self.ui.stopButton.clicked.emit()

    def select_emotion(self):
        self.emotion_selected = True
        self._update_status()
        self._update_phrase_numbers()

    def confirm_name(self):
        self.name_confirmed = True
        self._update_status()
        self._update_phrase_numbers()

    def edit_name(self):
        self.name_confirmed = False
        self._update_status()
        self._update_phrase_numbers()

    def open_file_dialog(self):
        dname = QFileDialog.getExistingDirectory(self, 'Select Directory')
        self.dataset_path = dname
        self.ui.dirPath.setText(dname)
        self._update_status()
        self._update_phrase_numbers()

    def start_recording(self):
        self.file_path = self._get_save_path()
        # initialize stream
        audio_device_index = self._get_audio_device_index()
        for device in AudioDevice().list_devices():
            if device['index'] == audio_device_index:
                channels = device['channels']
        # TODO: Now I set `channels=1` to make the audio file to be mono.
        # It's only for the current audio interface. It's supposed to be
        # variable `channels`. Also it can be improved by specifying a certain
        # channel of input device, and always making the audio file mono.
        self.recording_file = Recorder(channels=1).open(
            self.file_path, audio_device_index)
        self.recording_file.start_recording()
        # update objects
        # update the buttons' status
        self.is_recording = True
        self._update_status()
        # clean up any text in promptLabel
        self.ui.promptLabel.setText('')
        # start counting
        self.timer.start(1000)

    def stop_recording(self):
        self.recording_file.stop_recording()
        self.recording_file.close()
        # clean up
        # update the buttons' status and phrase numbers
        self.is_recording = False
        self._update_status()
        self._update_phrase_numbers()
        # reset the timer
        self.timer.stop()
        self._reset_time()
        # show the path
        self.ui.promptLabel.setText('Saved file to: ' + self.file_path)
        # reset the file path
        self.file_path = ''

    def timer_event(self):
        self.time = self.time.addSecs(1)
        self.ui.timeLabel.setText(self.time.toString('mm:ss'))

    def _update_status(self):
        # Update the buttons of name confirmation
        if self.name_confirmed:
            self.ui.editButton.setEnabled(True)
            self.ui.confirmButton.setEnabled(False)
            self.ui.nameEdit.setEnabled(False)
        else:
            self.ui.editButton.setEnabled(False)
            self.ui.confirmButton.setEnabled(True)
            self.ui.nameEdit.setEnabled(True)

        # Users can press record only after confirming the name
        # and selecting a emotion.
        self.ready_to_record = self.emotion_selected and self.name_confirmed and self.dataset_path != ''
        if self.ready_to_record:
            if self.is_recording:
                self.ui.recordButton.setEnabled(False)
                self.ui.stopButton.setEnabled(True)
                for emotionButton in self.emotion_buttons:
                    emotionButton.setEnabled(False)
            else:
                self.ui.recordButton.setEnabled(True)
                self.ui.stopButton.setEnabled(False)
                for emotionButton in self.emotion_buttons:
                    emotionButton.setEnabled(True)
        else:
            self.ui.recordButton.setEnabled(False)
            self.ui.stopButton.setEnabled(False)

    def _set_audio_device_box(self):
        # format: "idx - device name"
        devices = AudioDevice().list_devices()
        items = []
        for device in devices:
            index = device['index']
            name = device['name']
            item = str(index) + ' - ' + name
            items.append(item)
        self.ui.audioDeviceBox.addItems(items)

    def _get_audio_device_index(self):
        # return the number at the beginning as the index
        return int(
            re.match('\d+', self.ui.audioDeviceBox.currentText()).group())

    def _set_midi_device_box(self):
        devices = MidiDevice().list_devices()
        self.ui.midiDeviceBox.addItems(devices)

    def _open_midi_device(self):
        def callback_start():
            if self.ready_to_record:
                if self.ui.recordButton.isEnabled():
                    self.ui.recordButton.clicked.emit()

        def callback_end():
            if self.ready_to_record:
                if self.ui.stopButton.isEnabled():
                    self.ui.stopButton.clicked.emit()

        device_name = self.ui.midiDeviceBox.currentText()
        if device_name != '':
            midi_pedal = MidiPedal(start_note=48, end_note=60)
            midi_pedal.open_device(device_name, callback_start, callback_end)

    def _reset_time(self):
        self.time = QtCore.QTime(0, 0, 0)
        self.ui.timeLabel.setText('00:00')

    def _get_emotion(self):
        for emotion in self.emotion_set:
            if self.emotion_button_dict[emotion].isChecked():
                return emotion

    def _get_name(self):
        return self.ui.nameEdit.text()

    def _get_instruemt(self):
        return self.ui.instrumentBox.currentText()

    def _get_save_path(self):
        emotion = self._get_emotion()
        instrument = self._get_instruemt()
        name = self._get_name()
        dir_path = os.path.join(self.dataset_path, emotion, instrument)
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)
        filename = name + '-' + datetime.datetime.now().strftime(
            '%Y-%m-%d-%H-%M-%S') + '.wav'
        file_path = os.path.join(dir_path, filename)
        return file_path

    def _update_phrase_numbers(self):
        phrase_numbers = {emotion: 0 for emotion in self.emotion_set}
        instrument = self._get_instruemt()
        # count the phrase numbers of each emotion
        for emotion in self.emotion_set:
            dir_path = os.path.join(self.dataset_path, emotion, instrument)
            # no directory means no phrase of this emotion has been recorded
            if not os.path.exists(dir_path):
                continue
            # count the number of files
            for filename in os.listdir(dir_path):
                if re.match('^' + self._get_name(), filename):
                    phrase_numbers[emotion] += 1
        # update the number display
        for emotion in self.emotion_set:
            # display the number when it's bigger than 0
            if phrase_numbers[emotion] > 0:
                self.emotion_button_dict[emotion].setText(
                    emotion + '(' + str(phrase_numbers[emotion]) + ')')
            else:
                self.emotion_button_dict[emotion].setText(emotion)
Exemplo n.º 2
0
            logging.debug("The {} iteration!".format(cnt))

            lidar_data, extra_data = vlp.update()
            if not args.no_camera:
                frame = shot(cam)
                data_dict = {
                    "lidar_data": lidar_data,
                    "extra_data": extra_data,
                    "frame": frame
                }
            else:
                data_dict = {
                    "lidar_data": lidar_data,
                    "extra_data": extra_data
                }
            recorder.add(data_dict)
            cnt += 1
            if args.timestep > 0 and cnt == args.timestep:
                break
    except KeyboardInterrupt:
        logging.critical("KEYBOARD INTERRUPTED!")
    finally:
        et = time.time()
        logging.info(
            "Recording Finish! It take {} seconds and collect {} data! Average FPS {}."
            .format(et - st, cnt, cnt / (et - st)))
        close_vlp(vlp)
        if not args.no_camera:
            close_camera(cam)
        recorder.close()