From aaaed6155493a1452a05ed058a39c9a7447bf11e Mon Sep 17 00:00:00 2001 From: Philipp Date: Wed, 6 Mar 2024 15:57:37 +0100 Subject: [PATCH] Fixed issue with inconsistent click sound (now using psychopy instead of playsound). Updated PySide to version 6.6.2. --- README.md | 2 +- raw/clickhi.wav | Bin 20022 -> 0 bytes raw/clicklo.wav | Bin 20022 -> 0 bytes requirements.txt | 4 +-- ui/About.py | 4 +-- ui/MeasurementCtrl.py | 59 ++++++++++++++++++------------------------ util/params.py | 4 +-- 7 files changed, 31 insertions(+), 42 deletions(-) delete mode 100644 raw/clickhi.wav delete mode 100644 raw/clicklo.wav diff --git a/README.md b/README.md index eabb64b..0ee6ffe 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ The app is started via `python start.py`. You can compile an executable/application for windows/mac via `pyinstaller start_win.spec` or `pyinstaller start_mac.spec`. # License -Copyright 2023 Dr.-Ing. Philipp Bulling +Copyright 2024 Dr.-Ing. Philipp Bulling This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/raw/clickhi.wav b/raw/clickhi.wav deleted file mode 100644 index 35799a7c4cf4f510d1ed62bd9c1446108d565700..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20022 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 cxYN)IcG5k#DHmx7!fg`f+#uX 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 diff --git a/requirements.txt b/requirements.txt index bd851c7..68e1a0a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,9 +7,9 @@ Adafruit-PlatformDetect==3.38.0 Adafruit-PureIO==1.1.9 hidapi==0.12.0.post2 numpy -playsound==1.2.2 +psychopy PyObjC; sys_platform == 'darwin' platformdirs pyinstaller pyqtgraph -PySide6==6.4.2 +PySide6==6.6.2 diff --git a/ui/About.py b/ui/About.py index 2eda106..ec037ff 100644 --- a/ui/About.py +++ b/ui/About.py @@ -37,10 +37,10 @@ def __init__(self): linkLabel.setOpenExternalLinks(True) licenseLabel = QLabel("The graphical user interface was built with PySide6 and PyQtGraph. The Circuit Pyhton driver \"cedargrove_nau7802\" is used to interface the NAU7802 ADC.\n\n" - "If you encounter any issues, please reach out to philippbulling@gmail.com.") + "If you encounter any issues, please reach out to philipp.bulling@hs-esslingen.de.") licenseLabel.setWordWrap(True) - nameLabel = QLabel("Copyright 2023 Dr.-Ing. Philipp Bulling") + nameLabel = QLabel("Copyright 2024 Dr.-Ing. Philipp Bulling") versionLabel = QLabel("Software Version: " + Params.version.value) layout.addWidget(aboutLabel) diff --git a/ui/MeasurementCtrl.py b/ui/MeasurementCtrl.py index 0987ce7..2ea76c4 100644 --- a/ui/MeasurementCtrl.py +++ b/ui/MeasurementCtrl.py @@ -21,13 +21,16 @@ from PySide6.QtWidgets import QWidget from PySide6.QtGui import QAction import pyqtgraph as pg -from playsound import playsound + +from psychopy import prefs +prefs.hardware['audioLib'] = ['ptb'] +from psychopy import sound +from psychopy import logging +logging.console.setLevel(logging.ERROR) + import numpy as np import time, datetime -from threading import Thread -from threading import Event - from ui.MeasurementGui import Ui_Form from util.repeatedTimer import RepeatedTimer from util.params import Params @@ -117,34 +120,16 @@ def __init__(self, weightSensor): #======================================== # Audio handling #======================================== - self.stopAudioThreadEvent = Event() - ####################################################################### - # TODO: Do it like this, as soon as PySide6.5.0 is available: - #self.soundHi = QSoundEffect(parent) # parent = MainWindow - #self.soundHi.setSource(QUrl.fromLocalFile(Params.fileClickHi.value)) - #self.soundHi.setVolume(1.0) - ####################################################################### - self.playSndHiEvent = Event() - self.playSndLoEvent = Event() + self.clickHi = sound.Sound(value='E', secs=0.1, octave=5) + self.clickLo = sound.Sound(value='C', secs=0.1, octave=5) # Start a timer that is only used for the tare display self.tareTimer = RepeatedTimer(1/self.fsMeas, self.onTareVisualization) - #======================================== - # Callback functions - #======================================== - def onAudioPlayback(self, stopEvent, playHi, playLo): - while(True): - if stopEvent.is_set(): - stopEvent.clear() - break - if playHi.is_set(): - playHi.clear() - playsound(Params.fileClickHi.value) - if playLo.is_set(): - playLo.clear() - playsound(Params.fileClickLo.value) - time.sleep(0.001) # Necessary to reduce priority of this thread?! + ################################################## + # Only for debugging resons. + self.OLD_TIME = time.time() + ################################################## def onStartMeasurement(self): if not self.running: @@ -156,16 +141,13 @@ def onStartMeasurement(self): self.weightSpinBox.setEnabled(False) self.tareButton.setEnabled(False) - self.audioThread = Thread(target=self.onAudioPlayback, args=(self.stopAudioThreadEvent, self.playSndHiEvent, self.playSndLoEvent)) - self.audioThread.start() self.measurementTimer = RepeatedTimer(1/self.fsMeas, self.onMeasurementCallback) + self.running = True def onStopMeasurement(self): if self.running: self.measurementTimer.stop() - self.stopAudioThreadEvent.set() - self.audioThread.join() self.running = False self.measCnt = 0 @@ -212,10 +194,19 @@ def onMeasurementCallback(self): # Set the events for the click-playback if secCnt > 0: + self.clickHi.stop() + self.clickLo.stop() if (self.lookupTable[secCnt] > self.lookupTable[secCnt-1]): - self.playSndHiEvent.set() + self.clickHi.play() elif (self.lookupTable[secCnt] < self.lookupTable[secCnt-1]) or (self.countdown[secCnt] < 4 and self.lookupTable[secCnt] == 0): - self.playSndLoEvent.set() + self.clickLo.play() + + ################################################## + # Only for debugging reasons: Print elapsed time. + NEW_TIME = time.time() + print("Elapsed time: " + str(round(NEW_TIME - self.OLD_TIME, 2)) + " s") + self.OLD_TIME = NEW_TIME + ################################################## # Increase the repetition- and set counter if self.countdown[secCnt] == 1 and self.lookupTable[secCnt] == 0: diff --git a/util/params.py b/util/params.py index 1e07db1..a1c3a60 100644 --- a/util/params.py +++ b/util/params.py @@ -37,9 +37,7 @@ class Params(Enum): logFile = os.path.join(datadir, 'debug.log') workoutCfgFile = os.path.join(basedir, 'settings/workouts.csv') - fileClickHi = os.path.join(basedir, 'raw/clickhi.wav') - fileClickLo = os.path.join(basedir, 'raw/clicklo.wav') appIcon = os.path.join(basedir, 'raw/icon.ico') appName = APPNAME appAuthor = APPAUTHOR - version = '1.2.1' + version = '1.3.0'