Multiple fixes. SNR calculation still needs fixing

This commit is contained in:
2020-01-12 18:56:19 +00:00
parent 210b5c8bd5
commit e955b746d1
19 changed files with 313 additions and 58 deletions
+1
View File
@@ -22,6 +22,7 @@ import scipy.signal as signal
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
def asl_P56(x, fs, nbits): def asl_P56(x, fs, nbits):
nbits = int(nbits)
eps = np.finfo(float).eps eps = np.finfo(float).eps
x = x[:] # make sure x is column vector x = x[:] # make sure x is column vector
if len(x.shape) < 2: if len(x.shape) < 2:
+1
View File
@@ -26,6 +26,7 @@ g = exp( -1/( fs* T)); % smoothing factor in envelop detection
c( 1: thres_no)= 2.^ (-15: thres_no- 16); c( 1: thres_no)= 2.^ (-15: thres_no- 16);
% vector with thresholds from one quantizing level up to half the maximum % vector with thresholds from one quantizing level up to half the maximum
% code, at a step of 2, in the case of 16bit samples, from 2^-15 to 0.5; % code, at a step of 2, in the case of 16bit samples, from 2^-15 to 0.5;
a( 1: thres_no) = 0; % activity counter for each level threshold a( 1: thres_no) = 0; % activity counter for each level threshold
hang( 1: thres_no) = I; % hangover counter for each level threshold hang( 1: thres_no) = I; % hangover counter for each level threshold
+9 -8
View File
@@ -3,8 +3,8 @@
"fileversion" : 1, "fileversion" : 1,
"appversion" : { "appversion" : {
"major" : 8, "major" : 8,
"minor" : 0, "minor" : 1,
"revision" : 8, "revision" : 1,
"architecture" : "x64", "architecture" : "x64",
"modernui" : 1 "modernui" : 1
} }
@@ -159,11 +159,12 @@
"fontname" : "Arial", "fontname" : "Arial",
"fontsize" : 12.0, "fontsize" : 12.0,
"id" : "obj-18", "id" : "obj-18",
"linecount" : 2,
"maxclass" : "comment", "maxclass" : "comment",
"numinlets" : 1, "numinlets" : 1,
"numoutlets" : 0, "numoutlets" : 0,
"patching_rect" : [ 408.0, 215.0, 81.75, 20.0 ], "patching_rect" : [ 408.0, 215.0, 81.75, 33.0 ],
"text" : "70 dB SPL" "text" : "70 dB Peak SPL"
} }
} }
@@ -684,8 +685,8 @@
"followglobaltempo" : 0, "followglobaltempo" : 0,
"formantcorrection" : 0, "formantcorrection" : 0,
"mode" : "basic", "mode" : "basic",
"originallength" : [ 866265.382312924717553, "ticks" ], "originallength" : [ 866265.382312924601138, "ticks" ],
"originaltempo" : 119.999999999999943, "originaltempo" : 119.999999999999929,
"pitchcorrection" : 0, "pitchcorrection" : 0,
"quality" : "basic", "quality" : "basic",
"timestretch" : [ 0 ] "timestretch" : [ 0 ]
@@ -969,8 +970,8 @@
"followglobaltempo" : 0, "followglobaltempo" : 0,
"formantcorrection" : 0, "formantcorrection" : 0,
"mode" : "basic", "mode" : "basic",
"originallength" : [ 137594.144217686989577, "ticks" ], "originallength" : [ 137594.144217686960474, "ticks" ],
"originaltempo" : 119.999999999999929, "originaltempo" : 119.999999999999915,
"pitchcorrection" : 0, "pitchcorrection" : 0,
"quality" : "basic", "quality" : "basic",
"timestretch" : [ 0 ] "timestretch" : [ 0 ]
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
sys.path.insert(0, "../matrix_test/helper_modules")
import numpy as np
from pathops import dir_must_exist
from filesystem import globDir
from pysndfile import sndio
import os
from signalops import block_process_wav
import matplotlib.pyplot as plt
def main():
'''
'''
fs = 44100
f = 1000.0
n = np.arange(fs * 60 * 5)
y = np.sin(2*np.pi*f*n/fs)
coef = np.load('./out/calibration_coefficients/click_cal_coef.npy')
y *= coef
dir_must_exist('./out/calibrated_stim/')
sndio.write("./out/calibrated_stim/1k_tone.wav", y, fs, format='wav', enc='pcm16')
coef = np.load('./out/calibration_coefficients/da_cal_coef.npy')
y, fs, enc = sndio.read('./out/stimulus/da_cal_stim.wav')
sndio.write('./out/calibrated_stim/da_cal_stim.wav', y*coef, fs, format='wav', enc='pcm16')
coef = np.load('./out/calibration_coefficients/mat_cal_coef.npy')
y, fs, enc = sndio.read('./out/stimulus/mat_cal_stim.wav')
sndio.write('./out/calibrated_stim/mat_cal_stim.wav', y*coef, fs, format='wav', enc='pcm16')
coef = np.load('./out/calibration_coefficients/story_cal_coef.npy')
y, fs, enc = sndio.read('./out/stimulus/story_cal_stim.wav')
sndio.write('./out/calibrated_stim/story_cal_stim.wav', y*coef, fs, format='wav', enc='pcm16')
if __name__ == "__main__":
main()
+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
sys.path.insert(0, "../matrix_test/helper_modules")
import numpy as np
from pathops import dir_must_exist
from filesystem import globDir
from pysndfile import sndio
import os
from signalops import block_process_wav
from shutil import copyfile
def calc_potential_max(wavs, noise_filepath, out_dir, out_name):
max_wav_samp = 0
max_wav_rms = 0
for wav in wavs:
x, fs, enc = sndio.read(wav)
max_wav_samp = np.max([max_wav_samp, np.max(np.abs(x))])
max_wav_rms = np.max([max_wav_rms, np.sqrt(np.mean(x**2))])
x, fs, enc = sndio.read(noise_filepath)
noise_rms = np.sqrt(np.mean(x**2))
max_noise_samp = max(np.abs(x))
snr = -5.
snr_fs = 10**(-snr/20)
max_noise_samp *= max_wav_rms/noise_rms
max_sampl = max_wav_samp+(max_noise_samp*snr_fs)
reduction_coef = 1.0/max_sampl
np.save(os.path.join(out_dir, "{}.npy".format(out_name)), reduction_coef)
return reduction_coef
def main():
'''
'''
da_files = ["../tone_stim/stimulus/tone_2000/tone_3000_2000Hz.wav", "../tone_stim/stimulus/tone_500/tone_3000_500Hz.wav"]
story_dir = "../eeg_story_stim/stimulus"
mat_dir = "../matrix_test/speech_components"
noise_file = "../matrix_test/behavioural_stim/stimulus/wav/noise/noise_norm.wav"
da_noise_file = "../da_stim/noise/wav/noise/noise_norm.wav"
story_wavs = globDir(story_dir, '*.wav')
mat_wavs = globDir(mat_dir, '*.wav')
out_dir = "./out"
out_red_dir = os.path.join(out_dir, 'reduction_coefficients')
out_stim_dir = os.path.join(out_dir, 'stimulus')
dir_must_exist(out_dir)
dir_must_exist(out_red_dir)
dir_must_exist(out_stim_dir)
story_coef = calc_potential_max(story_wavs, noise_file, out_red_dir, "story_red_coef")
mat_coef = calc_potential_max(mat_wavs, noise_file, out_red_dir, "mat_red_coef")
da_coef = calc_potential_max(da_files, da_noise_file, out_red_dir, "da_red_coef")
mat_cal_stim = "../matrix_test/long_concat_stim/out/stim/stim_0.wav"
da_cal_stim = "./out/stimulus/1k_tone.wav"
# click_cal_stim = "../tone_stim/stimulus/tone_2000/tone_3000_2000Hz.wav"
story_cal_stim = "../eeg_story_stim/stimulus/odin_1_1.wav"
mat_out_stim = os.path.join(out_stim_dir, "mat_cal_stim.wav")
# click_out_stim = os.path.join(out_stim_dir, "click_cal_stim.wav")
da_out_stim = os.path.join(out_stim_dir, "1k_cal_stim.wav")
story_out_stim = os.path.join(out_stim_dir, "story_cal_stim.wav")
block_process_wav(mat_cal_stim, mat_out_stim, lambda x: x * mat_coef)
block_process_wav(story_cal_stim, story_out_stim, lambda x: x * story_coef)
block_process_wav(da_cal_stim, da_out_stim, lambda x: x * da_coef)
# block_process_wav(click_cal_stim, click_out_stim, lambda x: x * click_coef)
#copyfile(click_cal_stim, click_out_stim)
if __name__ == "__main__":
main()
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
sys.path.insert(0, "../matrix_test/helper_modules")
import numpy as np
from pathops import dir_must_exist
from filesystem import globDir
from pysndfile import sndio
import os
from signalops import block_process_wav
import matplotlib.pyplot as plt
def main():
'''
'''
fs = 44100
f = 1000.0
n = np.arange(fs * 60 * 5)
y = np.sin(2*np.pi*f*n/fs)
y = np.array([y, y]).T
sndio.write("./out/stimulus/1k_tone.wav", y, fs, format='wav', enc='pcm16')
if __name__ == "__main__":
main()
+1 -1
View File
@@ -44,7 +44,7 @@ class DaTestThread(BaseThread):
''' '''
def __init__(self, sessionFilepath=None, def __init__(self, sessionFilepath=None,
stimFolder='./tone_stim/stimulus', stimFolder='./tone_stim/stimulus',
noiseFilepath="./tone_stim/noise/wav/noise/noise.wav", noiseFilepath="./tone_stim/noise/wav/noise/noise_norm.wav",
noiseintensityFilepath="./tone_stim/noise/intensity/noise_intensity.npy", noiseintensityFilepath="./tone_stim/noise/intensity/noise_intensity.npy",
red_coef="./calibration/out/reduction_coefficients/tone_red_coef.npy", red_coef="./calibration/out/reduction_coefficients/tone_red_coef.npy",
cal_coef="./calibration/out/calibration_coefficients/tone_cal_coef.npy", cal_coef="./calibration/out/calibration_coefficients/tone_cal_coef.npy",
+1 -1
View File
@@ -16,8 +16,8 @@ def main():
wavs = globDir("./stimulus", "*.wav") wavs = globDir("./stimulus", "*.wav")
for wav in wavs: for wav in wavs:
x, fs, enc, fmt = sndio.read(wav, return_format=True) x, fs, enc, fmt = sndio.read(wav, return_format=True)
y_r = np.insert(x, 0, np.zeros(fs))
idx = np.arange(x.shape[0]) idx = np.arange(x.shape[0])
breakpoint()
y = np.vstack([x, x, np.zeros(x.shape[0])]).T y = np.vstack([x, x, np.zeros(x.shape[0])]).T
trigger = gen_trigger(idx, 2., 0.01, fs) trigger = gen_trigger(idx, 2., 0.01, fs)
y[:, 2] = trigger y[:, 2] = trigger
+2 -2
View File
@@ -1,3 +1,3 @@
1, Who are the characters of this story? 1, Who are the characters of this story?
2, What are they up to? 2, What are the characters doing?
3, What did they wager? 3, What did the characters wager?
1 1 Who are the characters of this story?
2 2 What are they up to? What are the characters doing?
3 3 What did they wager? What did the characters wager?
+30 -9
View File
@@ -19,6 +19,9 @@ import csv
import pdb import pdb
import dill import dill
import sounddevice as sd
from hearing_loss_sim import apply_hearing_loss_sim
symb_dict = { symb_dict = {
True: 10003, True: 10003,
False: 10007 False: 10007
@@ -38,7 +41,7 @@ class EEGStoryTrainThread(BaseThread):
Thread for running server side matrix test operations Thread for running server side matrix test operations
''' '''
def __init__(self, sessionFilepath=None, def __init__(self, sessionFilepath=None,
stimFolder='./eeg_story_stim/', nTrials=2, stimFolder='./eeg_story_stim/stimulus/', nTrials=2,
socketio=None, participant=None, srt_50=None, s_50=None): socketio=None, participant=None, srt_50=None, s_50=None):
self.test_name = 'eeg_story_train' self.test_name = 'eeg_story_train'
self.stimDir = stimFolder self.stimDir = stimFolder
@@ -90,6 +93,7 @@ class EEGStoryTrainThread(BaseThread):
if self._stopevent.isSet() or self.finishTest: if self._stopevent.isSet() or self.finishTest:
break break
# Play concatenated matrix sentences at set SNR # Play concatenated matrix sentences at set SNR
self.playStimulus(wav) self.playStimulus(wav)
self.waitForResponse() self.waitForResponse()
if self._stopevent.isSet() or self.finishTest: if self._stopevent.isSet() or self.finishTest:
@@ -142,21 +146,38 @@ class EEGStoryTrainThread(BaseThread):
def displayInstructions(self): def displayInstructions(self):
self.socketio.emit('display_instructions', namespace='/main') self.socketio.emit('display_instructions', namespace='/main')
def playStimulus(self, wav):
def playStimulus(self, wav_file, replay=False): '''
Output audio stimulus from numpy array
'''
self.newResp = False self.newResp = False
self.socketio.emit("stim_playing", namespace="/main") self.socketio.emit("stim_playing", namespace="/main")
# if not replay: x, fs, _ = sndio.read(wav)
# self.y = self.generateTrial(self.snr) if self.participant.parameters['hl_sim_active']:
y = apply_hearing_loss_sim(x, fs)
# Play audio # Play audio
# sd.play(self.y, self.fs, blocking=True)
if not self.dev_mode: if not self.dev_mode:
self.play_wav(wav_file, 'finish_test') sd.play(y, fs, blocking=True)
else: else:
self.play_wav('./da_stim/DA_170.wav', 'finish_test') self.play_wav('./da_stim/DA_170.wav', '')
self.socketio.emit("stim_done", namespace="/main") self.socketio.emit("stim_done", namespace="/main")
# def playStimulus(self, wav_file, replay=False):
# x, fs, _ = sndio.read(wav_file)
# self.newResp = False
# self.socketio.emit("stim_playing", namespace="/main")
# # if not replay:
# # self.y = self.generateTrial(self.snr)
# # Play audio
# # sd.play(self.y, self.fs, blocking=True)
# if not self.dev_mode:
# self.play_wav(wav_file, 'finish_test')
# else:
# self.play_wav('./da_stim/DA_170.wav', 'finish_test')
# self.socketio.emit("stim_done", namespace="/main")
def saveState(self, out="test_state.pkl"): def saveState(self, out="test_state.pkl"):
saveDict = {k:self.__dict__[k] for k in self.toSave} saveDict = {k:self.__dict__[k] for k in self.toSave}
+28 -7
View File
@@ -10,7 +10,10 @@ import numpy as np
import pandas as pd import pandas as pd
from shutil import copy2 from shutil import copy2
import re import re
import sounddevice as sd
from ITU_P56 import asl_P56
from hearing_loss_sim import apply_hearing_loss_sim
from test_base import BaseThread, run_test_thread from test_base import BaseThread, run_test_thread
from scipy.special import logit from scipy.special import logit
from config import socketio from config import socketio
@@ -52,7 +55,7 @@ class EEGTestThread(BaseThread):
''' '''
def __init__(self, sessionFilepath=None, def __init__(self, sessionFilepath=None,
listFolder="./matrix_test/short_concat_stim/out", listFolder="./matrix_test/short_concat_stim/out",
noiseFilepath="./matrix_test/behavioural_stim/stimulus/wav/noise/noise.wav", noiseFilepath="./matrix_test/behavioural_stim/stimulus/wav/noise/noise_norm.wav",
red_coef="./calibration/out/reduction_coefficients/mat_red_coef.npy", red_coef="./calibration/out/reduction_coefficients/mat_red_coef.npy",
cal_coef="./calibration/out/calibration_coefficients/mat_cal_coef.npy", cal_coef="./calibration/out/calibration_coefficients/mat_cal_coef.npy",
socketio=None, participant=None, srt_50=None, s_50=None): socketio=None, participant=None, srt_50=None, s_50=None):
@@ -116,7 +119,7 @@ class EEGTestThread(BaseThread):
logger.info("{0:<25}".format("Current question 2:") + f"{' '.join(q[1][:-1])} | Answer: {q[1][-1]}") logger.info("{0:<25}".format("Current question 2:") + f"{' '.join(q[1][:-1])} | Answer: {q[1][-1]}")
logger.info("{0:<25}".format("Current SNR(-srt):") + f"{snr}") logger.info("{0:<25}".format("Current SNR(-srt):") + f"{snr}")
# Play concatenated matrix sentences at set SNR # Play concatenated matrix sentences at set SNR
self.playStimulusWav(wav) self.playStimulus(wav)
self.setMatrix(q) self.setMatrix(q)
self.saveState(out=self.backupFilepath) self.saveState(out=self.backupFilepath)
logger.info("-"*78) logger.info("-"*78)
@@ -171,8 +174,8 @@ class EEGTestThread(BaseThread):
def finaliseResults(self): def finaliseResults(self):
toSave = ['marker_files', 'clinPageLoaded', 'wav_files', 'participant', toSave = ['marker_files', 'clinPageLoaded', 'wav_files', 'participant',
'response', 'backupFilepath', 'noise_path', 'question_files', 'response', 'backupFilepath', 'noise_path', 'question_files',
'si', 'question', 'answers', 'trial_ind'] 'question', 'answers', 'trial_ind']
saveDict = {k:self.__dict__[k] for k in toSave} saveDict = {k:self.__dict__[k] for k in toSave if k in self.__dict__.keys()}
self.participant['eeg_test'].update(saveDict) self.participant['eeg_test'].update(saveDict)
self.participant.save("eeg_test") self.participant.save("eeg_test")
backup_path = os.path.join(self.participant.data_paths['eeg_test'], backup_path = os.path.join(self.participant.data_paths['eeg_test'],
@@ -240,20 +243,22 @@ class EEGTestThread(BaseThread):
csv_files = natsorted(globDir(stim_dir, "*.csv")) csv_files = natsorted(globDir(stim_dir, "*.csv"))
marker_file = csv_files[0] marker_file = csv_files[0]
question_files = csv_files[1:] question_files = csv_files[1:]
rms_file = globDir(stim_dir, "*.npy")[0] # rms_file = globDir(stim_dir, "*.npy")[0]
speech_rms = float(np.load(rms_file)) # speech_rms = float(np.load(rms_file))
snr = snrs[:, ind] snr = snrs[:, ind]
audio, fs, enc, fmt = sndio.read(wav, return_format=True) audio, fs, enc, fmt = sndio.read(wav, return_format=True)
speech = audio[:, :2] speech = audio[:, :2]
triggers = audio[:, 2] triggers = audio[:, 2]
speech_rms, _, _ = asl_P56(speech, fs, 16.)
wf = [] wf = []
wm = [] wm = []
for ind2, s in enumerate(snr): for ind2, s in enumerate(snr):
start = randint(0, noise_file.frames()-speech.shape[0]) start = randint(0, noise_file.frames()-speech.shape[0])
noise_file.seek(start) noise_file.seek(start)
noise = noise_file.read_frames(speech.shape[0]) noise = noise_file.read_frames(speech.shape[0])
noise_rms = np.sqrt(np.mean(noise**2)) #noise_rms = np.sqrt(np.mean(noise**2))
noise_rms = asl_P56(noise, fs, 16)
snr_fs = 10**(-s/20) snr_fs = 10**(-s/20)
if snr_fs == np.inf: if snr_fs == np.inf:
snr_fs = 0. snr_fs = 0.
@@ -302,6 +307,22 @@ class EEGTestThread(BaseThread):
self.answers[:] = np.nan self.answers[:] = np.nan
def playStimulus(self, wav):
'''
Output audio stimulus from numpy array
'''
self.newResp = False
self.socketio.emit("stim_playing", namespace="/main")
x, fs, _ = sndio.read(wav)
if self.participant.parameters['hl_sim_active']:
y = apply_hearing_loss_sim(x, fs)
# Play audio
if not self.dev_mode:
sd.play(y, fs, blocking=True)
else:
self.play_wav('./da_stim/DA_170.wav', '')
self.socketio.emit("{}_stim_done".format(self.test_name), namespace="/main")
def submitTestResponse(self, msg): def submitTestResponse(self, msg):
''' '''
Get and store participant response for current trial Get and store participant response for current trial
+3 -1
View File
@@ -18,6 +18,7 @@ import os
from pathlib import Path from pathlib import Path
from datetime import datetime from datetime import datetime
import re import re
from copy import deepcopy
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
nowtime = datetime.now() nowtime = datetime.now()
@@ -42,7 +43,7 @@ def find_participants(folder='./participant_data/'):
if os.path.isdir(os.path.join(folder,o))] if os.path.isdir(os.path.join(folder,o))]
for path in part_folder: for path in part_folder:
part_key = os.path.basename(path) part_key = os.path.basename(path)
participants[part_key] = Participant(participant_dir=path) participants[part_key] = deepcopy(Participant(participant_dir=path))
participants[part_key].load('info') participants[part_key].load('info')
participants[part_key].load('parameters') participants[part_key].load('parameters')
return participants return participants
@@ -144,6 +145,7 @@ class Participant:
''' '''
''' '''
folder = os.path.join(self.participant_dir, data_key) folder = os.path.join(self.participant_dir, data_key)
# print(f"Participant {self.data['info']['number']}: {folder}")
with open(os.path.join(folder, "{}.pkl".format(data_key)), 'rb') as f: with open(os.path.join(folder, "{}.pkl".format(data_key)), 'rb') as f:
self.data[data_key].update(dill.load(f)) self.data[data_key].update(dill.load(f))
+13
View File
@@ -0,0 +1,13 @@
from scipy import signal
import matplotlib.pyplot as plt
import numpy as np
def apply_hearing_loss_sim(x, fs, channels=[0, 1]):
b, a = signal.butter(4, 1170.0/(fs/2.), 'low')
if len(x.shape) < 2:
x = x[:, np.newaxis]
for channel in channels:
x[:, channel] = signal.filtfilt(b, a, x[:, channel])
return x
# w, h = signal.freqs(b, a)
+51 -17
View File
@@ -3,6 +3,8 @@
import sys import sys
#sys.path.insert(0, "../helper_modules") #sys.path.insert(0, "../helper_modules")
#sys.path.insert(0, "../matrix_test/helper_modules/") #sys.path.insert(0, "../matrix_test/helper_modules/")
sys.path.insert(0, "../../")
sys.path.insert(0, "../helper_modules")
import argparse import argparse
import os import os
@@ -16,6 +18,11 @@ from natsort import natsorted
from collections import namedtuple from collections import namedtuple
from pysndfile import PySndfile, sndio from pysndfile import PySndfile, sndio
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from ITU_P56 import asl_P56
from pathlib import Path
from multiprocessing.dummy import Pool as ThreadPool
import multiprocessing
from pathops import dir_must_exist from pathops import dir_must_exist
from signalops import rolling_window_lastaxis, block_lfilter, calc_rms, block_process_wav from signalops import rolling_window_lastaxis, block_lfilter, calc_rms, block_process_wav
@@ -191,7 +198,7 @@ def calc_spectrum(files, silences, fs=44100, plot=False):
return b return b
def gen_noise(OutDir, b, fs, s_rms): def gen_noise(OutDir, b, fs):
print("Generating noise...") print("Generating noise...")
# Generate 10 minutes of white noise # Generate 10 minutes of white noise
x = np.random.randn(int(fs*60.*5.)) x = np.random.randn(int(fs*60.*5.))
@@ -203,9 +210,14 @@ def gen_noise(OutDir, b, fs, s_rms):
dir_must_exist(noiseDir) dir_must_exist(noiseDir)
y, y_max = block_lfilter_wav(b, [1.0], x, os.path.join(noiseDir, 'noise.wav'), 65538, 44100) y, y_max = block_lfilter_wav(b, [1.0], x, os.path.join(noiseDir, 'noise.wav'), 65538, 44100)
block_process_wav(os.path.join(noiseDir, 'noise.wav'), os.path.join(noiseDir, 'noise_norm.wav'), lambda x: x / (y_max * 1.05)) block_process_wav(os.path.join(noiseDir, 'noise.wav'), os.path.join(noiseDir, 'noise_norm.wav'), lambda x: x / (y_max * 1.05))
noise_norm_wav = PySndfile(os.path.join(noiseDir, 'noise_norm.wav'), 'r')
noise_rms_path = os.path.join(noiseRMSDir, 'noise_rms.npy') noise_rms_path = os.path.join(noiseRMSDir, 'noise_rms.npy')
y = noise_norm_wav.read_frames(fs*60)
y = y/(np.abs(y).max() * 0.95) y = y/(np.abs(y).max() * 0.95)
rms = np.sqrt(np.mean(y**2)) # rms = np.sqrt(np.mean(y**2))
rms, _, _ = asl_P56(y, fs, 16)
print(f"Noise level: {rms}")
peak = np.abs(y).max() peak = np.abs(y).max()
np.save(noise_rms_path, rms) np.save(noise_rms_path, rms)
np.save('./stimulus/peak/noise_peak.npy', peak) np.save('./stimulus/peak/noise_peak.npy', peak)
@@ -215,21 +227,43 @@ def gen_noise(OutDir, b, fs, s_rms):
def calc_speech_rms(files, silences, rmsDir, fs=44100, plot=False): def calc_speech_rms(files, silences, rmsDir, fs=44100, plot=False):
''' '''
''' '''
files = files[:3]
#silences = silences[:3]
f = sum(files, []) f = sum(files, [])
sumsqrd = 0.0 n_files = len(f)
n = 0 #for ind, (wavfile, sil) in enumerate(zip(f, silences)):
for wavfile, sil in zip(f, silences): def level_calc(args):
y, fs, _ = sndio.read(wavfile) ind, wavfile = args
t = np.arange(y.size) x, fs, _ = sndio.read(wavfile)
sTemp = np.zeros((sil.shape[0], t.size), dtype=bool) level = asl_P56(x, fs, 16.)[0]
for ind3, s in enumerate(sil): print(f"Calculated level of {Path(wavfile).name} ({ind+1}/{n_files}): {level}")
sTemp[ind3, :] = np.logical_and(t > s[0], t < s[1]) return level
silentSamples = np.any(sTemp, axis=0)
y_temp = y[~silentSamples] # Make the Pool of workers
sumsqrd += np.sum(y_temp**2) pool = ThreadPool(multiprocessing.cpu_count()-1)
n += y_temp.size # Open the urls in their own threads
rms = np.sqrt(sumsqrd/n) # and return the results
np.save(os.path.join(rmsDir, 'overall_speech_rms.npy'), rms) levels = pool.map(level_calc, enumerate(f))
#close the pool and wait for the work to finish
pool.close()
pool.join()
rms = np.mean(levels)
# f = sum(files, [])
# sumsqrd = 0.0
# n = 0
# for wavfile, sil in zip(f, silences):
# y, fs, _ = sndio.read(wavfile)
# t = np.arange(y.size)
# sTemp = np.zeros((sil.shape[0], t.size), dtype=bool)
# for ind3, s in enumerate(sil):
# sTemp[ind3, :] = np.logical_and(t > s[0], t < s[1])
# silentSamples = np.any(sTemp, axis=0)
# y_temp = y[~silentSamples]
# sumsqrd += np.sum(y_temp**2)
# n += y_temp.size
# rms = np.sqrt(sumsqrd/n)
#np.save(os.path.join(rmsDir, 'overall_speech_rms.npy'), rms)
return rms return rms
#sentenceFFT.append(np.abs(Zxx[:, ~np.any(sTemp, axis=0)])) #sentenceFFT.append(np.abs(Zxx[:, ~np.any(sTemp, axis=0)]))
@@ -268,4 +302,4 @@ if __name__ == "__main__":
silences = detect_silences(rmsFiles, 44100) silences = detect_silences(rmsFiles, 44100)
s_rms = calc_speech_rms(wavFiles, silences, rmsDir) s_rms = calc_speech_rms(wavFiles, silences, rmsDir)
b = calc_spectrum(wavFiles, silences) b = calc_spectrum(wavFiles, silences)
y = gen_noise(args['OutDir'], b, 44100, s_rms) y = gen_noise(args['OutDir'], b, 44100)
+1
View File
@@ -98,6 +98,7 @@ def block_process_wav(wavpath, out_wavpath, func, block_size=4096, **args):
y = func(x, **args) y = func(x, **args)
out_wav.write_frames(y) out_wav.write_frames(y)
i += block_size i += block_size
del out_wav
def window_rms(a, window_size): def window_rms(a, window_size):
print("Squaring...") print("Squaring...")
@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import sys import sys
sys.path.insert(0, "../helper_modules/") sys.path.insert(0, "../helper_modules/")
sys.path.insert(0, "../../")
import os import os
from filesystem import globDir from filesystem import globDir
@@ -17,17 +18,27 @@ import csv
from copy import copy from copy import copy
from contextlib import ExitStack from contextlib import ExitStack
from scipy.signal import square from scipy.signal import square
from ITU_P56 import asl_P56
from pathlib import Path
def calc_potential_max(stim_folder, noise_filepath, out_dir): def calc_potential_max(stim_folder, noise_filepath, out_dir):
max_wav_samp = 0 max_wav_samp = 0
max_wav_rms = 0 max_wav_rms = 0
wavs = globDir(stim_folder, '*.wav') wavs = globDir(stim_folder, '*.wav')
for wav in wavs: n_files = len(wavs)
for ind, wav in enumerate(wavs):
x, fs, enc = sndio.read(wav) x, fs, enc = sndio.read(wav)
max_wav_samp = np.max([max_wav_samp, np.max(np.abs(x))]) max_wav_samp = np.max([max_wav_samp, np.max(np.abs(x))])
max_wav_rms = np.max([max_wav_rms, np.sqrt(np.mean(x**2))]) #max_wav_rms = np.max([max_wav_rms, np.sqrt(np.mean(x**2))])
level = asl_P56(x, fs, 16.)[0]
max_wav_rms = np.max([max_wav_rms, ])
print(f"Calculated level of {Path(wav).name} ({ind+1}/{n_files}): {level}")
x, fs, enc = sndio.read(noise_filepath) x, fs, enc = sndio.read(noise_filepath)
noise_rms = np.sqrt(np.mean(x**2)) # noise_rms = np.sqrt(np.mean(x**2))
print(f"Calculating level of {Path(noise_filepath).name}")
noise_rms, _, _ = asl_P56(x, fs, 16.)
print(f"Calculated level of {Path(noise_filepath).name}: {noise_rms}")
max_noise_samp = max(np.abs(x)) max_noise_samp = max(np.abs(x))
snr = -15.0 snr = -15.0
@@ -56,7 +67,7 @@ def main():
dir_must_exist(wav_dir) dir_must_exist(wav_dir)
dir_must_exist(noise_dir) dir_must_exist(noise_dir)
noise_filepath = "../behavioural_stim/stimulus/wav/noise/noise.wav" noise_filepath = "../behavioural_stim/stimulus/wav/noise/noise_norm.wav"
folders = os.listdir(base_dir) folders = os.listdir(base_dir)
folders = natsorted(folders)[1:15] folders = natsorted(folders)[1:15]
+14 -4
View File
@@ -21,6 +21,9 @@ import sounddevice as sd
import pdb import pdb
from config import socketio from config import socketio
from hearing_loss_sim import apply_hearing_loss_sim
from ITU_P56 import asl_P56
from pathlib import Path
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -143,6 +146,7 @@ class MatTestThread(BaseThread):
self.loadNoise(noiseFilepath, noiseRMSFilepath) self.loadNoise(noiseFilepath, noiseRMSFilepath)
self.dev_mode = False self.dev_mode = False
self.audio_cal = False
def displayInstructions(self): def displayInstructions(self):
@@ -185,6 +189,8 @@ class MatTestThread(BaseThread):
self.lists[0][currentSentenceInd], self.lists[0][currentSentenceInd],
self.listsRMS[0][currentSentenceInd] self.listsRMS[0][currentSentenceInd]
) )
if self.participant.parameters['hl_sim_active']:
self.y = apply_hearing_loss_sim(self.y, self.fs, channels=[0])
# Define words presented in the current trial # Define words presented in the current trial
self.currentWords = self.listsString[0][currentSentenceInd] self.currentWords = self.listsString[0][currentSentenceInd]
@@ -193,7 +199,11 @@ class MatTestThread(BaseThread):
logger.info("{0:<25}".format("Current track index:") + f"{self.adTrInd}") logger.info("{0:<25}".format("Current track index:") + f"{self.adTrInd}")
logger.info("{0:<25}".format("Current trial number:") + f"{self.trialN}") logger.info("{0:<25}".format("Current trial number:") + f"{self.trialN}")
logger.info("{0:<25}".format("Current SNR:") + f"{self.adaptiveTracks[self.adTrInd].snr}") logger.info("{0:<25}".format("Current SNR:") + f"{self.adaptiveTracks[self.adTrInd].snr}")
self.playStimulus(self.y, self.fs) if self.audio_cal:
y, fs, fmt = sndio.read('./calibration/out/stimulus/mat_cal_stim.wav')
self.playStimulus(y, fs)
else:
self.playStimulus(self.y, self.fs)
self.waitForResponse() self.waitForResponse()
self.checkSentencesAvailable() self.checkSentencesAvailable()
if self.finishTest: if self.finishTest:
@@ -388,9 +398,9 @@ class MatTestThread(BaseThread):
# Get data for each sentence # Get data for each sentence
for fp, words, level_file in zip(listAudiofiles, csv_reader, levels): for fp, words, level_file in zip(listAudiofiles, csv_reader, levels):
# Read in audio file and calculate it's RMS # Read in audio file and calculate it's RMS
level = loadmat(level_file)
x, self.fs, _ = sndio.read(fp) x, self.fs, _ = sndio.read(fp)
x_rms = np.sqrt(np.mean(x**2)) logger.info(f"Calculating level for {Path(fp).name}")
x_rms, _, _ = asl_P56(x, self.fs, 16.)
self.lists[-1].append(x) self.lists[-1].append(x)
self.listsRMS[-1].append(x_rms) self.listsRMS[-1].append(x_rms)
self.listsString[-1].append(words) self.listsString[-1].append(words)
@@ -531,7 +541,7 @@ class AdaptiveTrack():
x_noise *= x_rms/self.noise_rms x_noise *= x_rms/self.noise_rms
y = x_noise y = x_noise
# Set speech to start 500ms after the noise, scaled to the desired SNR # Set speech to start 500ms after the noise, scaled to the desired SNR
sigStart = random.randint(self.fs, round(2*self.fs)) sigStart = random.randint(round(self.fs/2.), round(2*self.fs))
y[sigStart:sigStart+x.size] += x*snr_fs y[sigStart:sigStart+x.size] += x*snr_fs
y *= self.reduction_coef y *= self.reduction_coef
return y return y
+3 -3
View File
@@ -20,13 +20,13 @@
<div class="form-group container-fluid"> <div class="form-group container-fluid">
<div class="row"> <div class="row">
<div class="col text-center mb-3"> <div class="col text-center mb-3">
<button type="button" id="start_mat_train" class="btn btn-primary mx-3">Start matrix training data collection</button> <button type="button" id="start_story_train" class="btn btn-primary mx-3">Start story training data collection</button>
</div> </div>
<div class="col text-center mb-3"> <div class="col text-center mb-3">
<button type="button" id="load_mat_train_saved" class="btn btn-primary mx-3">Load saved session</button> <button type="button" id="load_train_story_saved" class="btn btn-primary mx-3">Load saved session</button>
</div> </div>
<div class="col text-center mb-3"> <div class="col text-center mb-3">
<button type="button" id="load_mat_train_backup" class="btn btn-primary mx-3">Load previous automatic backup</button> <button type="button" id="load_train_story_backup" class="btn btn-primary mx-3">Load previous automatic backup</button>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
+1 -1
View File
@@ -74,7 +74,7 @@
</a> </a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown"> <div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="/pta_test">PTA</a> <a class="dropdown-item" href="/pta_test">PTA</a>
<a class="dropdown-item" href="/tympanometry">Tympanometry</a> <!--<a class="dropdown-item" href="/tympanometry">Tympanometry</a>-->
<a class="dropdown-item" href="/da/setup">Tone EEG recording</a> <a class="dropdown-item" href="/da/setup">Tone EEG recording</a>
<a class="dropdown-item" href="/matrix_test">Behavioral Matrix Test</a> <a class="dropdown-item" href="/matrix_test">Behavioral Matrix Test</a>
<a class="dropdown-item" href="/eeg">Decoder EEG recording</a> <a class="dropdown-item" href="/eeg">Decoder EEG recording</a>