Administrator approval is now required for registering new accounts. If you are registering a new account, and are external to the University, please ask the repository owner to contact ServiceLine to request your account be approved. Repository owners must include the newly registered email address, and specific repository in the request for approval.

Commit b1a0a2af authored by Ed Rogers's avatar Ed Rogers
Browse files

Create basic GUI, threading of playback stream and logging

parent ba380ea2
<?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
<?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
......@@ -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__':
......
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]
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment