diff --git a/.idea/HearingTest.iml b/.idea/HearingTest.iml index 68465087f3b4614f37821c1207c99e2999094723..dbdac814511d2f5ba7c405193f6ced38ce4fc087 100644 --- a/.idea/HearingTest.iml +++ b/.idea/HearingTest.iml @@ -1,8 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <module type="PYTHON_MODULE" version="4"> <component name="NewModuleRootManager"> - <content url="file://$MODULE_DIR$" /> - <orderEntry type="jdk" jdkName="Python 3.6 GUI (QT)" jdkType="Python SDK" /> + <orderEntry type="jdk" jdkName="Python 3.5 (pyGUI)" jdkType="Python SDK" /> <orderEntry type="sourceFolder" forTests="false" /> </component> </module> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index df360948d62e8e86b209adfda8e202f3a58bec82..945a951c03ef1b2e2487fd8103e600a990a26051 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> - <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6 GUI (QT)" project-jdk-type="Python SDK" /> + <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.5 (pyGUI)" project-jdk-type="Python SDK" /> </project> \ No newline at end of file diff --git a/HearingTest.py b/HearingTest.py index c11639cdfdfc97440c27503e21b63cf256873317..078d329bbbfa7505c527a8c085b7baa9187fc2e0 100644 --- a/HearingTest.py +++ b/HearingTest.py @@ -24,30 +24,108 @@ import numpy as np import matplotlib.pyplot as plt import soundfile as sf import time - - -class SoundLibrary: - def __init__(self, fs, sample_length, freqs): - self._data = {} - self.fs = fs - self.sample_length = sample_length - self.generate_sounds(freqs) - - def generate_sounds(self, freqs): - t = np.arange(0, self.sample_length, 1 / self.fs) - for f in freqs: - sound = np.sin(2 * np.pi * f * t) - self._data[f] = sound - - @property - def freqs(self): - return self._data.keys() - - def play(self, freq): - sd.play(self[freq], self.fs, blocking=False) - - def __getitem__(self, item): - return self._data[item] +from PyQt5 import QtCore, QtWidgets, QtGui +from PyQt5.QtCore import Qt +from PyQt5.QtWidgets import QMainWindow, QLabel, QGridLayout, QWidget, QTextEdit +from PyQt5.QtCore import QSize +import sys +from SoundLibrary import SoundLibrary +import random + + +class TestThread(QtCore.QThread): + played_sound = QtCore.pyqtSignal(float, float) + + def __init__(self, library: SoundLibrary): + QtCore.QThread.__init__(self) + self.library = library + + def __del__(self): + self.wait() + + # def _get_top_post(self, subreddit): + # """ + # Return a pre-formatted string with top post title, author, + # and subreddit name from the subreddit passed as the only required + # argument. + # + # :param subreddit: A valid subreddit name + # :type subreddit: str + # :return: A string with top post title, author, + # and subreddit name from that subreddit. + # :rtype: str + # """ + # url = "https://www.reddit.com/r/{}.json?limit=1".format(subreddit) + # headers = {'User-Agent': 'nikolak@outlook.com tutorial code'} + # request = urllib2.Request(url, headers=headers) + # response = urllib2.urlopen(request) + # data = json.load(response) + # top_post = data['data']['children'][0]['data'] + # return "'{title}' by {author} in {subreddit}".format(**top_post) + + def run(self): + """ + + """ + for _ in range(5): + volume = random.random() + freq = random.choice(list(self.library.freqs)) + self.library.play(freq, volume) + self.played_sound.emit(freq, volume) + self.sleep(1) + + +class HelloWindow(QMainWindow): + def __init__(self, library): + self.library = library + self.testing_thread = None + self.test_running = False + + QMainWindow.__init__(self) + + self.setMinimumSize(QSize(640, 480)) + self.setWindowTitle("Hearing Test") + + central_widget = QWidget(self) + self.setCentralWidget(central_widget) + + grid_layout = QGridLayout(self) + central_widget.setLayout(grid_layout) + + self.title = QLabel("Press any key to start...", self) + self.title.setAlignment(QtCore.Qt.AlignCenter) + + self.log = QTextEdit() + self.log.setReadOnly(True) + self.log.setFocusPolicy(QtCore.Qt.NoFocus) + + grid_layout.addWidget(self.title, 0, 0) + grid_layout.addWidget(self.log, 1, 0) + + def keyPressEvent(self, event: QtGui.QKeyEvent): + if not self.test_running: + self.test_running = True + self.run_test() + else: + self.record_key_press(event) + + def record_key_press(self, event): + self.log.append('Key {} pressed at {}'.format(event.key(), time.clock())) + + def run_test(self): + self.log.append('Starting...') + self.testing_thread = TestThread(self.library) + self.testing_thread.played_sound.connect(self.sound_played) + self.testing_thread.finished.connect(self.test_finished) + self.testing_thread.start() + # need to prevent another thread starting + + def sound_played(self, freq, volume): + self.log.append('Played freq {}, at volume {} and time {}'.format(freq, volume, time.clock())) + + def test_finished(self): + self.test_running = False + self.log.append('Finished test') def main(): @@ -55,12 +133,17 @@ def main(): device = sd.query_devices(sd.default.device['output']) fs = device['default_samplerate'] length = 0.5 - f = [20, 50, 100, 200, 500, 1000, 2000, 5000, 10000] + f = [100, 200, 500, 1000, 2000, 5000, 10000] library = SoundLibrary(fs, length, f) - for freq in sorted(library.freqs): - library.play(freq) - time.sleep(1) + # for freq in sorted(library.freqs): + # library.play(freq) + # time.sleep(1) + + app = QtWidgets.QApplication(sys.argv) + main_win = HelloWindow(library) + main_win.show() + sys.exit(app.exec_()) if __name__ == '__main__': diff --git a/SoundLibrary.py b/SoundLibrary.py new file mode 100644 index 0000000000000000000000000000000000000000..b752aaaab90c20f30a47df290e11534314c38d17 --- /dev/null +++ b/SoundLibrary.py @@ -0,0 +1,28 @@ + +import numpy as np +import sounddevice as sd +from typing import List + + +class SoundLibrary: + def __init__(self, fs: float, sample_length: int, freqs: List[float]): + self._data = {} + self.fs = fs + self.sample_length = sample_length + self.generate_sounds(freqs) + + def generate_sounds(self, freqs: List[float]): + t = np.arange(0, self.sample_length, 1 / self.fs) + for f in freqs: + sound = np.sin(2 * np.pi * f * t) + self._data[f] = sound + + @property + def freqs(self): + return self._data.keys() + + def play(self, freq: float, volume: float=1) -> None: + sd.play(self[freq]*volume, self.fs, blocking=False) + + def __getitem__(self, item: float): + return self._data[item]