Multiple fixes. SNR calculation still needs fixing
This commit is contained in:
@@ -22,6 +22,7 @@ import scipy.signal as signal
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def asl_P56(x, fs, nbits):
|
||||
nbits = int(nbits)
|
||||
eps = np.finfo(float).eps
|
||||
x = x[:] # make sure x is column vector
|
||||
if len(x.shape) < 2:
|
||||
|
||||
@@ -26,6 +26,7 @@ g = exp( -1/( fs* T)); % smoothing factor in envelop detection
|
||||
c( 1: thres_no)= 2.^ (-15: thres_no- 16);
|
||||
% 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;
|
||||
|
||||
a( 1: thres_no) = 0; % activity counter for each level threshold
|
||||
hang( 1: thres_no) = I; % hangover counter for each level threshold
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"fileversion" : 1,
|
||||
"appversion" : {
|
||||
"major" : 8,
|
||||
"minor" : 0,
|
||||
"revision" : 8,
|
||||
"minor" : 1,
|
||||
"revision" : 1,
|
||||
"architecture" : "x64",
|
||||
"modernui" : 1
|
||||
}
|
||||
@@ -159,11 +159,12 @@
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-18",
|
||||
"linecount" : 2,
|
||||
"maxclass" : "comment",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 0,
|
||||
"patching_rect" : [ 408.0, 215.0, 81.75, 20.0 ],
|
||||
"text" : "70 dB SPL"
|
||||
"patching_rect" : [ 408.0, 215.0, 81.75, 33.0 ],
|
||||
"text" : "70 dB Peak SPL"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -684,8 +685,8 @@
|
||||
"followglobaltempo" : 0,
|
||||
"formantcorrection" : 0,
|
||||
"mode" : "basic",
|
||||
"originallength" : [ 866265.382312924717553, "ticks" ],
|
||||
"originaltempo" : 119.999999999999943,
|
||||
"originallength" : [ 866265.382312924601138, "ticks" ],
|
||||
"originaltempo" : 119.999999999999929,
|
||||
"pitchcorrection" : 0,
|
||||
"quality" : "basic",
|
||||
"timestretch" : [ 0 ]
|
||||
@@ -969,8 +970,8 @@
|
||||
"followglobaltempo" : 0,
|
||||
"formantcorrection" : 0,
|
||||
"mode" : "basic",
|
||||
"originallength" : [ 137594.144217686989577, "ticks" ],
|
||||
"originaltempo" : 119.999999999999929,
|
||||
"originallength" : [ 137594.144217686960474, "ticks" ],
|
||||
"originaltempo" : 119.999999999999915,
|
||||
"pitchcorrection" : 0,
|
||||
"quality" : "basic",
|
||||
"timestretch" : [ 0 ]
|
||||
|
||||
Executable
+38
@@ -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()
|
||||
Executable
+74
@@ -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()
|
||||
Executable
+27
@@ -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
@@ -44,7 +44,7 @@ class DaTestThread(BaseThread):
|
||||
'''
|
||||
def __init__(self, sessionFilepath=None,
|
||||
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",
|
||||
red_coef="./calibration/out/reduction_coefficients/tone_red_coef.npy",
|
||||
cal_coef="./calibration/out/calibration_coefficients/tone_cal_coef.npy",
|
||||
|
||||
@@ -16,8 +16,8 @@ def main():
|
||||
wavs = globDir("./stimulus", "*.wav")
|
||||
for wav in wavs:
|
||||
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])
|
||||
breakpoint()
|
||||
y = np.vstack([x, x, np.zeros(x.shape[0])]).T
|
||||
trigger = gen_trigger(idx, 2., 0.01, fs)
|
||||
y[:, 2] = trigger
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
1, Who are the characters of this story?
|
||||
2, What are they up to?
|
||||
3, What did they wager?
|
||||
2, What are the characters doing?
|
||||
3, What did the characters wager?
|
||||
|
@@ -19,6 +19,9 @@ import csv
|
||||
import pdb
|
||||
import dill
|
||||
|
||||
import sounddevice as sd
|
||||
from hearing_loss_sim import apply_hearing_loss_sim
|
||||
|
||||
symb_dict = {
|
||||
True: 10003,
|
||||
False: 10007
|
||||
@@ -38,7 +41,7 @@ class EEGStoryTrainThread(BaseThread):
|
||||
Thread for running server side matrix test operations
|
||||
'''
|
||||
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):
|
||||
self.test_name = 'eeg_story_train'
|
||||
self.stimDir = stimFolder
|
||||
@@ -90,6 +93,7 @@ class EEGStoryTrainThread(BaseThread):
|
||||
if self._stopevent.isSet() or self.finishTest:
|
||||
break
|
||||
# Play concatenated matrix sentences at set SNR
|
||||
|
||||
self.playStimulus(wav)
|
||||
self.waitForResponse()
|
||||
if self._stopevent.isSet() or self.finishTest:
|
||||
@@ -142,21 +146,38 @@ class EEGStoryTrainThread(BaseThread):
|
||||
def displayInstructions(self):
|
||||
self.socketio.emit('display_instructions', namespace='/main')
|
||||
|
||||
|
||||
def playStimulus(self, wav_file, replay=False):
|
||||
def playStimulus(self, wav):
|
||||
'''
|
||||
Output audio stimulus from numpy array
|
||||
'''
|
||||
self.newResp = False
|
||||
self.socketio.emit("stim_playing", namespace="/main")
|
||||
# if not replay:
|
||||
# self.y = self.generateTrial(self.snr)
|
||||
x, fs, _ = sndio.read(wav)
|
||||
if self.participant.parameters['hl_sim_active']:
|
||||
y = apply_hearing_loss_sim(x, fs)
|
||||
# Play audio
|
||||
# sd.play(self.y, self.fs, blocking=True)
|
||||
if not self.dev_mode:
|
||||
self.play_wav(wav_file, 'finish_test')
|
||||
sd.play(y, fs, blocking=True)
|
||||
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")
|
||||
|
||||
# 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"):
|
||||
saveDict = {k:self.__dict__[k] for k in self.toSave}
|
||||
|
||||
+28
-7
@@ -10,7 +10,10 @@ import numpy as np
|
||||
import pandas as pd
|
||||
from shutil import copy2
|
||||
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 scipy.special import logit
|
||||
from config import socketio
|
||||
@@ -52,7 +55,7 @@ class EEGTestThread(BaseThread):
|
||||
'''
|
||||
def __init__(self, sessionFilepath=None,
|
||||
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",
|
||||
cal_coef="./calibration/out/calibration_coefficients/mat_cal_coef.npy",
|
||||
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 SNR(-srt):") + f"{snr}")
|
||||
# Play concatenated matrix sentences at set SNR
|
||||
self.playStimulusWav(wav)
|
||||
self.playStimulus(wav)
|
||||
self.setMatrix(q)
|
||||
self.saveState(out=self.backupFilepath)
|
||||
logger.info("-"*78)
|
||||
@@ -171,8 +174,8 @@ class EEGTestThread(BaseThread):
|
||||
def finaliseResults(self):
|
||||
toSave = ['marker_files', 'clinPageLoaded', 'wav_files', 'participant',
|
||||
'response', 'backupFilepath', 'noise_path', 'question_files',
|
||||
'si', 'question', 'answers', 'trial_ind']
|
||||
saveDict = {k:self.__dict__[k] for k in toSave}
|
||||
'question', 'answers', 'trial_ind']
|
||||
saveDict = {k:self.__dict__[k] for k in toSave if k in self.__dict__.keys()}
|
||||
self.participant['eeg_test'].update(saveDict)
|
||||
self.participant.save("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"))
|
||||
marker_file = csv_files[0]
|
||||
question_files = csv_files[1:]
|
||||
rms_file = globDir(stim_dir, "*.npy")[0]
|
||||
speech_rms = float(np.load(rms_file))
|
||||
# rms_file = globDir(stim_dir, "*.npy")[0]
|
||||
# speech_rms = float(np.load(rms_file))
|
||||
snr = snrs[:, ind]
|
||||
audio, fs, enc, fmt = sndio.read(wav, return_format=True)
|
||||
|
||||
speech = audio[:, :2]
|
||||
triggers = audio[:, 2]
|
||||
speech_rms, _, _ = asl_P56(speech, fs, 16.)
|
||||
wf = []
|
||||
wm = []
|
||||
for ind2, s in enumerate(snr):
|
||||
start = randint(0, noise_file.frames()-speech.shape[0])
|
||||
noise_file.seek(start)
|
||||
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)
|
||||
if snr_fs == np.inf:
|
||||
snr_fs = 0.
|
||||
@@ -302,6 +307,22 @@ class EEGTestThread(BaseThread):
|
||||
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):
|
||||
'''
|
||||
Get and store participant response for current trial
|
||||
|
||||
+3
-1
@@ -18,6 +18,7 @@ import os
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
import re
|
||||
from copy import deepcopy
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
nowtime = datetime.now()
|
||||
@@ -42,7 +43,7 @@ def find_participants(folder='./participant_data/'):
|
||||
if os.path.isdir(os.path.join(folder,o))]
|
||||
for path in part_folder:
|
||||
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('parameters')
|
||||
return participants
|
||||
@@ -144,6 +145,7 @@ class Participant:
|
||||
'''
|
||||
'''
|
||||
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:
|
||||
self.data[data_key].update(dill.load(f))
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
import sys
|
||||
#sys.path.insert(0, "../helper_modules")
|
||||
#sys.path.insert(0, "../matrix_test/helper_modules/")
|
||||
sys.path.insert(0, "../../")
|
||||
sys.path.insert(0, "../helper_modules")
|
||||
|
||||
import argparse
|
||||
import os
|
||||
@@ -16,6 +18,11 @@ from natsort import natsorted
|
||||
from collections import namedtuple
|
||||
from pysndfile import PySndfile, sndio
|
||||
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 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
|
||||
|
||||
|
||||
def gen_noise(OutDir, b, fs, s_rms):
|
||||
def gen_noise(OutDir, b, fs):
|
||||
print("Generating noise...")
|
||||
# Generate 10 minutes of white noise
|
||||
x = np.random.randn(int(fs*60.*5.))
|
||||
@@ -203,9 +210,14 @@ def gen_noise(OutDir, b, fs, s_rms):
|
||||
dir_must_exist(noiseDir)
|
||||
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))
|
||||
noise_norm_wav = PySndfile(os.path.join(noiseDir, 'noise_norm.wav'), 'r')
|
||||
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)
|
||||
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()
|
||||
np.save(noise_rms_path, rms)
|
||||
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):
|
||||
'''
|
||||
'''
|
||||
files = files[:3]
|
||||
#silences = silences[:3]
|
||||
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)
|
||||
n_files = len(f)
|
||||
#for ind, (wavfile, sil) in enumerate(zip(f, silences)):
|
||||
def level_calc(args):
|
||||
ind, wavfile = args
|
||||
x, fs, _ = sndio.read(wavfile)
|
||||
level = asl_P56(x, fs, 16.)[0]
|
||||
print(f"Calculated level of {Path(wavfile).name} ({ind+1}/{n_files}): {level}")
|
||||
return level
|
||||
|
||||
# Make the Pool of workers
|
||||
pool = ThreadPool(multiprocessing.cpu_count()-1)
|
||||
# Open the urls in their own threads
|
||||
# and return the results
|
||||
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
|
||||
#sentenceFFT.append(np.abs(Zxx[:, ~np.any(sTemp, axis=0)]))
|
||||
|
||||
@@ -268,4 +302,4 @@ if __name__ == "__main__":
|
||||
silences = detect_silences(rmsFiles, 44100)
|
||||
s_rms = calc_speech_rms(wavFiles, silences, rmsDir)
|
||||
b = calc_spectrum(wavFiles, silences)
|
||||
y = gen_noise(args['OutDir'], b, 44100, s_rms)
|
||||
y = gen_noise(args['OutDir'], b, 44100)
|
||||
|
||||
@@ -98,6 +98,7 @@ def block_process_wav(wavpath, out_wavpath, func, block_size=4096, **args):
|
||||
y = func(x, **args)
|
||||
out_wav.write_frames(y)
|
||||
i += block_size
|
||||
del out_wav
|
||||
|
||||
def window_rms(a, window_size):
|
||||
print("Squaring...")
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
sys.path.insert(0, "../helper_modules/")
|
||||
sys.path.insert(0, "../../")
|
||||
|
||||
import os
|
||||
from filesystem import globDir
|
||||
@@ -17,17 +18,27 @@ import csv
|
||||
from copy import copy
|
||||
from contextlib import ExitStack
|
||||
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):
|
||||
max_wav_samp = 0
|
||||
max_wav_rms = 0
|
||||
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)
|
||||
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)
|
||||
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))
|
||||
|
||||
snr = -15.0
|
||||
@@ -56,7 +67,7 @@ def main():
|
||||
dir_must_exist(wav_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 = natsorted(folders)[1:15]
|
||||
|
||||
+13
-3
@@ -21,6 +21,9 @@ import sounddevice as sd
|
||||
import pdb
|
||||
|
||||
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
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -143,6 +146,7 @@ class MatTestThread(BaseThread):
|
||||
self.loadNoise(noiseFilepath, noiseRMSFilepath)
|
||||
|
||||
self.dev_mode = False
|
||||
self.audio_cal = False
|
||||
|
||||
|
||||
def displayInstructions(self):
|
||||
@@ -185,6 +189,8 @@ class MatTestThread(BaseThread):
|
||||
self.lists[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
|
||||
self.currentWords = self.listsString[0][currentSentenceInd]
|
||||
|
||||
@@ -193,6 +199,10 @@ class MatTestThread(BaseThread):
|
||||
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 SNR:") + f"{self.adaptiveTracks[self.adTrInd].snr}")
|
||||
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.checkSentencesAvailable()
|
||||
@@ -388,9 +398,9 @@ class MatTestThread(BaseThread):
|
||||
# Get data for each sentence
|
||||
for fp, words, level_file in zip(listAudiofiles, csv_reader, levels):
|
||||
# Read in audio file and calculate it's RMS
|
||||
level = loadmat(level_file)
|
||||
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.listsRMS[-1].append(x_rms)
|
||||
self.listsString[-1].append(words)
|
||||
@@ -531,7 +541,7 @@ class AdaptiveTrack():
|
||||
x_noise *= x_rms/self.noise_rms
|
||||
y = x_noise
|
||||
# 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 *= self.reduction_coef
|
||||
return y
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
<div class="form-group container-fluid">
|
||||
<div class="row">
|
||||
<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 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 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 class="row">
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<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="/matrix_test">Behavioral Matrix Test</a>
|
||||
<a class="dropdown-item" href="/eeg">Decoder EEG recording</a>
|
||||
|
||||
Reference in New Issue
Block a user