[audio] works
This commit is contained in:
parent
30717ed97a
commit
7c81a52fe9
@ -1,11 +1,10 @@
|
|||||||
from PyQt5.QtWidgets import QAction, QFormLayout, QGridLayout, QLabel, QLineEdit, QSizePolicy, QSlider, QSpinBox, QTextEdit, QWidget
|
from PyQt5.QtWidgets import QAction, QComboBox, QFormLayout, QGridLayout, QLabel, QLineEdit, QSizePolicy, QSlider, QSpinBox, QTextEdit, QWidget
|
||||||
from PyQt5.QtCore import QIODevice, QPoint, QTimer, Qt, pyqtSignal, QSettings, QUrl
|
from PyQt5.QtCore import QIODevice, QPoint, QRandomGenerator, QTimer, Qt, pyqtSignal, QSettings, QUrl
|
||||||
from PyQt5.QtGui import QColor, QFont, QKeySequence, QPainter, QBrush, QPen, QPixmap
|
from PyQt5.QtGui import QColor, QFont, QIntValidator, QKeySequence, QPainter, QBrush, QPen, QPixmap
|
||||||
from PyQt5.QtMultimedia import QSound, QMediaPlayer, QMediaContent, QAudio, QAudioDeviceInfo
|
from PyQt5.QtMultimedia import QSound, QMediaPlayer, QMediaContent, QAudio, QAudioDeviceInfo
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import blipblop.constants as cnst
|
import blipblop.constants as cnst
|
||||||
import numpy as np
|
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
|
|
||||||
class SettingsPanel(QWidget):
|
class SettingsPanel(QWidget):
|
||||||
@ -17,15 +16,23 @@ class SettingsPanel(QWidget):
|
|||||||
self._trial_spinner.setMaximum(25)
|
self._trial_spinner.setMaximum(25)
|
||||||
self._trial_spinner.setValue(10)
|
self._trial_spinner.setValue(10)
|
||||||
|
|
||||||
self._min_delay_edit = QLineEdit()
|
self._min_delay_spinner = QSpinBox()
|
||||||
self._min_delay_edit.setText(str("1000"))
|
self._min_delay_spinner.setMinimum(1)
|
||||||
self._min_delay_edit.setToolTip("Minimum delay between start of trial and stimulus display")
|
self._min_delay_spinner.setMaximum(10)
|
||||||
self._min_delay_edit.setEnabled(False)
|
self._min_delay_spinner.setValue(1)
|
||||||
|
self._min_delay_spinner.setToolTip("Minimum delay between start of trial and stimulus display [s]")
|
||||||
|
|
||||||
self._max_delay_edit = QLineEdit()
|
self._max_delay_spinner = QSpinBox()
|
||||||
self._max_delay_edit.setText(str("5000"))
|
self._max_delay_spinner.setMinimum(1)
|
||||||
self._max_delay_edit.setToolTip("Maximum delay between start of trial and stimulus display")
|
self._max_delay_spinner.setMaximum(10)
|
||||||
self._max_delay_edit.setEnabled(False)
|
self._max_delay_spinner.setValue(5)
|
||||||
|
self._max_delay_spinner.setToolTip("Maximum delay between start of trial and stimulus display [s]")
|
||||||
|
|
||||||
|
self._pause_spinner = QSpinBox()
|
||||||
|
self._pause_spinner.setMinimum(1)
|
||||||
|
self._pause_spinner.setMaximum(10)
|
||||||
|
self._pause_spinner.setValue(3)
|
||||||
|
self._pause_spinner.setToolTip("Pause between trials [s]")
|
||||||
|
|
||||||
self._saliency_slider = QSlider(Qt.Horizontal)
|
self._saliency_slider = QSlider(Qt.Horizontal)
|
||||||
self._saliency_slider.setMinimum(0)
|
self._saliency_slider.setMinimum(0)
|
||||||
@ -35,13 +42,9 @@ class SettingsPanel(QWidget):
|
|||||||
self._saliency_slider.setTickPosition(QSlider.TicksBelow)
|
self._saliency_slider.setTickPosition(QSlider.TicksBelow)
|
||||||
self._saliency_slider.setToolTip("Saliency of the stimulus, i.e. its opacity")
|
self._saliency_slider.setToolTip("Saliency of the stimulus, i.e. its opacity")
|
||||||
|
|
||||||
self._size_slider = QSlider(Qt.Horizontal)
|
self._sound_combo = QComboBox()
|
||||||
self._size_slider.setMinimum(0)
|
for k in cnst.SNDS_DICT.keys():
|
||||||
self._size_slider.setMaximum(200)
|
self._sound_combo.addItem(k)
|
||||||
self._size_slider.setSliderPosition(100)
|
|
||||||
self._size_slider.setTickInterval(25)
|
|
||||||
self._size_slider.setTickPosition(QSlider.TicksBelow)
|
|
||||||
self._size_slider.setToolTip("Diameter of the stimulus in pixel")
|
|
||||||
|
|
||||||
self._instructions = QTextEdit()
|
self._instructions = QTextEdit()
|
||||||
self._instructions.setMarkdown("* fixate central cross\n * press start (enter) when ready\n * press space bar as soon as the stimulus occurs")
|
self._instructions.setMarkdown("* fixate central cross\n * press start (enter) when ready\n * press space bar as soon as the stimulus occurs")
|
||||||
@ -51,10 +54,11 @@ class SettingsPanel(QWidget):
|
|||||||
form_layout = QFormLayout()
|
form_layout = QFormLayout()
|
||||||
form_layout.addRow("Settings", None)
|
form_layout.addRow("Settings", None)
|
||||||
form_layout.addRow("number of trials", self._trial_spinner)
|
form_layout.addRow("number of trials", self._trial_spinner)
|
||||||
form_layout.addRow("minimum delay [ms]", self._min_delay_edit)
|
form_layout.addRow("minimum delay [s]", self._min_delay_spinner)
|
||||||
form_layout.addRow("maximum delay [ms]", self._max_delay_edit)
|
form_layout.addRow("maximum delay [s]", self._max_delay_spinner)
|
||||||
|
form_layout.addRow("pause [s]", self._pause_spinner)
|
||||||
form_layout.addRow("stimulus saliency", self._saliency_slider)
|
form_layout.addRow("stimulus saliency", self._saliency_slider)
|
||||||
form_layout.addRow("stimulus size", self._size_slider)
|
form_layout.addRow("stimulus sound", self._sound_combo)
|
||||||
form_layout.addRow("instructions", self._instructions)
|
form_layout.addRow("instructions", self._instructions)
|
||||||
self.setLayout(form_layout)
|
self.setLayout(form_layout)
|
||||||
|
|
||||||
@ -72,15 +76,27 @@ class SettingsPanel(QWidget):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def min_delay(self):
|
def min_delay(self):
|
||||||
return int(self._min_delay_edit.text())
|
return self._min_delay_spinner.value()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def max_delay(self):
|
def max_delay(self):
|
||||||
return int(self._max_delay_edit.text())
|
return self._max_delay_spinner.value()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pause(self):
|
||||||
|
return self._pause_spinner.value()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sound(self):
|
||||||
|
return self._sound_combo.currentText()
|
||||||
|
|
||||||
def set_enabled(self, enabled):
|
def set_enabled(self, enabled):
|
||||||
self._trial_spinner.setEnabled(enabled)
|
self._trial_spinner.setEnabled(enabled)
|
||||||
self._saliency_slider.setEnabled(enabled)
|
self._saliency_slider.setEnabled(enabled)
|
||||||
|
self._pause_spinner.setEnabled(enabled)
|
||||||
|
self._min_delay_spinner.setEnabled(enabled)
|
||||||
|
self._max_delay_spinner.setEnabled(enabled)
|
||||||
|
self._sound_combo.setEnabled(False)
|
||||||
|
|
||||||
|
|
||||||
class AudioBlop(QWidget):
|
class AudioBlop(QWidget):
|
||||||
@ -101,8 +117,15 @@ class AudioBlop(QWidget):
|
|||||||
l.setPixmap(QPixmap(os.path.join(cnst.ICONS_FOLDER, "auditory_task.png")))
|
l.setPixmap(QPixmap(os.path.join(cnst.ICONS_FOLDER, "auditory_task.png")))
|
||||||
grid.addWidget(l, 0, 0, Qt.AlignLeft)
|
grid.addWidget(l, 0, 0, Qt.AlignLeft)
|
||||||
|
|
||||||
|
l2 =QLabel("Measurement of auditory reaction times\npress enter to start")
|
||||||
|
font = QFont()
|
||||||
|
font.setBold(True)
|
||||||
|
font.setPointSize(20)
|
||||||
|
l2.setFont(font)
|
||||||
|
l2.setStyleSheet("color: #2D4B9A")
|
||||||
|
grid.addWidget(l2, 0, 1, Qt.AlignLeft)
|
||||||
|
|
||||||
self._status_label = QLabel("Ready to start, press enter ...")
|
self._status_label = QLabel("Ready to start, press enter ...")
|
||||||
QFont
|
|
||||||
grid.addWidget(self._status_label, 3, 4, Qt.AlignBaseline)
|
grid.addWidget(self._status_label, 3, 4, Qt.AlignBaseline)
|
||||||
|
|
||||||
self._draw_area = QLabel()
|
self._draw_area = QLabel()
|
||||||
@ -122,7 +145,7 @@ class AudioBlop(QWidget):
|
|||||||
self._session_running = False
|
self._session_running = False
|
||||||
self._trial_running = False
|
self._trial_running = False
|
||||||
self._player = QMediaPlayer()
|
self._player = QMediaPlayer()
|
||||||
|
self._random_generator = QRandomGenerator()
|
||||||
self.setFocus()
|
self.setFocus()
|
||||||
|
|
||||||
def create_actions(self):
|
def create_actions(self):
|
||||||
@ -154,7 +177,6 @@ class AudioBlop(QWidget):
|
|||||||
else:
|
else:
|
||||||
reaction_time = self._response_time - self._start_time
|
reaction_time = self._response_time - self._start_time
|
||||||
self._reaction_times.append(reaction_time.total_seconds())
|
self._reaction_times.append(reaction_time.total_seconds())
|
||||||
self.reset_canvas()
|
|
||||||
self._trial_running = False
|
self._trial_running = False
|
||||||
|
|
||||||
def reset_canvas(self):
|
def reset_canvas(self):
|
||||||
@ -183,27 +205,11 @@ class AudioBlop(QWidget):
|
|||||||
|
|
||||||
def blip(self):
|
def blip(self):
|
||||||
self._player.play()
|
self._player.play()
|
||||||
# print(QAudioDeviceInfo.availableDevices(QAudio.AudioOutput))
|
|
||||||
#bells = cnst.get_sound("message")
|
|
||||||
#bells.setLoops(10)
|
|
||||||
#QSound("mysounds/bells.wav");
|
|
||||||
#bells.play();
|
|
||||||
stim_size = self._settings.size
|
|
||||||
painter = QPainter(self._draw_area.pixmap())
|
|
||||||
painter.setPen(QPen(Qt.red, 1, Qt.SolidLine))
|
|
||||||
color = QColor(Qt.red)
|
|
||||||
color.setAlphaF(self._settings.saliency/100)
|
|
||||||
painter.setBrush(QBrush(color, Qt.SolidPattern))
|
|
||||||
painter.drawEllipse(self._canvas_center, stim_size, stim_size)
|
|
||||||
painter.end()
|
|
||||||
self._start_time = dt.datetime.now()
|
self._start_time = dt.datetime.now()
|
||||||
self._draw_area.update()
|
|
||||||
|
|
||||||
def on_trial_start(self):
|
def on_trial_start(self):
|
||||||
print("start trial", self._trial_running)
|
|
||||||
if self._trial_running:
|
if self._trial_running:
|
||||||
return
|
return
|
||||||
print("start trial")
|
|
||||||
if not self._session_running:
|
if not self._session_running:
|
||||||
self._settings.set_enabled(False)
|
self._settings.set_enabled(False)
|
||||||
self._session_running = True
|
self._session_running = True
|
||||||
@ -213,15 +219,13 @@ class AudioBlop(QWidget):
|
|||||||
return
|
return
|
||||||
self._trial_counter += 1
|
self._trial_counter += 1
|
||||||
self._status_label.setText("Trial %i of %i running" % (self._trial_counter, self._settings.trials))
|
self._status_label.setText("Trial %i of %i running" % (self._trial_counter, self._settings.trials))
|
||||||
|
content = cnst.get_sound(self._settings.sound)
|
||||||
url = QUrl.fromLocalFile("/home/grewe/projects/programming/blipblop/sounds/message.wav")
|
|
||||||
content = cnst.get_sound("message")
|
|
||||||
self._player.setMedia(content)
|
self._player.setMedia(content)
|
||||||
self._player.setVolume(100)
|
self._player.setVolume(self._settings.saliency)
|
||||||
|
|
||||||
min_interval = int(self._settings.min_delay / 100)
|
min_interval = int(self._settings.min_delay * 10)
|
||||||
max_interval = int(self._settings.max_delay / 100)
|
max_interval = int(self._settings.max_delay * 10)
|
||||||
interval = np.random.randint(min_interval, max_interval, 1) * 100
|
interval = self._random_generator.bounded(min_interval, max_interval) * 100
|
||||||
self._start_time = None
|
self._start_time = None
|
||||||
timer = QTimer(self)
|
timer = QTimer(self)
|
||||||
timer.setSingleShot(True)
|
timer.setSingleShot(True)
|
||||||
@ -238,7 +242,6 @@ class AudioBlop(QWidget):
|
|||||||
return self._reaction_times()
|
return self._reaction_times()
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self.reset_canvas()
|
|
||||||
self._trial_counter = 0
|
self._trial_counter = 0
|
||||||
self._session_running = 0
|
self._session_running = 0
|
||||||
self._reaction_times = []
|
self._reaction_times = []
|
||||||
|
Loading…
Reference in New Issue
Block a user