-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a button to record new samples #77
base: master
Are you sure you want to change the base?
Changes from all commits
bfc975b
985eb33
3d526e3
9a2d3de
40f44c4
46b0bca
93bfe1b
91b8fb2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,3 +14,4 @@ Contents | |
tsv_format | ||
import_export | ||
api | ||
recording |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
Recording New Samples | ||
===================== | ||
|
||
New samples can be recorded directly from the application. | ||
|
||
Select the audio device you want to use and then press the `Record` button. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,14 @@ | ||
from PySide6.QtCore import QModelIndex, Slot | ||
import os | ||
import random | ||
import string | ||
from PySide6.QtCore import QModelIndex, QUrl, Slot | ||
from PySide6.QtMultimedia import ( | ||
QAudioInput, | ||
QMediaCaptureSession, | ||
QMediaDevices, | ||
QMediaFormat, | ||
QMediaRecorder, | ||
) | ||
from PySide6.QtWidgets import QFrame, QFileDialog, QPushButton, QWidget | ||
from voice_annotation_tool.annotation_list_model import AnnotationListModel | ||
from voice_annotation_tool.opened_project_frame_ui import Ui_OpenedProjectFrame | ||
|
@@ -50,10 +60,26 @@ def __init__(self): | |
self.audioPlaybackWidget.previous_pressed.connect(self.previous_pressed) | ||
self.project: Project | ||
self.annotationList.installEventFilter(self) | ||
|
||
for age in AGE_STRINGS: | ||
self.ageInput.addItem(age) | ||
self.ageInput.addItem(self.tr("[Multiple]")) | ||
|
||
self.recorder = QMediaRecorder() | ||
self.input = QAudioInput() | ||
self.session = QMediaCaptureSession() | ||
self.session.setAudioInput(self.input) | ||
self.recorder = QMediaRecorder() | ||
self.session.setRecorder(self.recorder) | ||
self.recorder.setMediaFormat(QMediaFormat.Wave) | ||
self.recorder.setEncodingMode(QMediaRecorder.ConstantBitRateEncoding) | ||
self.recorder.setAudioSampleRate(16000) | ||
self.recorder.setAudioBitRate(32) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think 16 Bit is the standard here, but I am unsure. |
||
self.recorder.setQuality(QMediaRecorder.HighQuality) | ||
|
||
for device in QMediaDevices.audioInputs(): | ||
self.deviceComboBox.addItem(device.description()) | ||
|
||
def get_playback_buttons(self) -> list[QPushButton]: | ||
"""Returns a list of buttons used to control the audio playback.""" | ||
return self.audioPlaybackWidget.playback_buttons | ||
|
@@ -164,7 +190,7 @@ def delete_selected(self): | |
"""Delete the selected annotations and audio files.""" | ||
for selected in self.get_selected_annotations(): | ||
self.project.delete_annotation(selected) | ||
self.annotationList.model().layoutChanged.emit() | ||
self.update_sample_list() | ||
self.update_metadata_widgets() | ||
|
||
def get_selected_annotations(self) -> list[Annotation]: | ||
|
@@ -176,6 +202,11 @@ def get_selected_annotations(self) -> list[Annotation]: | |
annotations.append(selected_index.data(AnnotationListModel.ANNOTATION_ROLE)) | ||
return annotations | ||
|
||
def update_sample_list(self): | ||
"""Update the graphical representation of the | ||
AnnotationListModel after it changed.""" | ||
self.annotationList.model().layoutChanged.emit() | ||
|
||
@Slot() | ||
def previous_pressed(self): | ||
current = self.annotationList.currentIndex().row() | ||
|
@@ -271,3 +302,23 @@ def import_profile_pressed(self): | |
def mark_unchanged_pressed(self): | ||
for annotation in self.get_selected_annotations(): | ||
self.project.mark_unchanged(annotation) | ||
|
||
@Slot() | ||
def record_pressed(self): | ||
if not self.project.audio_folder or not self.project.audio_folder.is_dir(): | ||
return | ||
if self.recorder.recorderState() == QMediaRecorder.StoppedState: | ||
name = "000" + "".join(random.choices("0123456789abcdef", k=125)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. random is difficult, as it might happen at random, that the same value is chosen, which might lead to bugs. |
||
path = QUrl.fromLocalFile(os.fspath(self.project.audio_folder / name)) | ||
self.recorder.setOutputLocation(path) | ||
self.recorder.record() | ||
self.recordButton.setText(self.tr("Stop Recording")) | ||
else: | ||
self.recorder.stop() | ||
self.recordButton.setText(self.tr("Record Sample")) | ||
self.project.load_audio_files(self.project.audio_folder) | ||
self.update_sample_list() | ||
|
||
@Slot() | ||
def device_selected(self, device: int): | ||
self.input.setDevice(QMediaDevices.audioInputs()[device]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose to record and save in full quality, e.g. 48000 kHz, and then reduce the sample rate later for training and inference