def gen_indexes(list_dir, speech_dir): list_files = globDir(list_dir, '*.txt') component_map_file = globDir(speech_dir, '*.json')[0] json_data = open(component_map_file).read() component_map = json.loads(json_data) column_names = ['a', 'b', 'c', 'd', 'e'] sentence_lists = {} for list_file in list_files: with open(list_file, 'r') as lfile: list_inds = [] list_strings = [] for line in lfile: line = line.split() trial_inds = [] for ind, word in enumerate(line): column_key = column_names[ind] column_words = component_map[column_key] trial_ind = column_words.index(word.upper()) trial_inds.append(trial_ind) list_inds.append(trial_inds) list_strings.append(line) head, tail = os.path.split(list_file) sl_key = os.path.splitext(tail)[0] sentence_lists[sl_key] = (np.array(list_inds), list_strings) return sentence_lists
def main(): wavs = globDir('./out/stim/', '*.wav') rmss = globDir('./out/stim/', 'stim_*_env.npy') outDir = "./out/stim/" for wav, rms in zip(wavs, rmss): print("Detecting silence in wav file: {}".format(wav)) snd = PySndfile(wav, 'r') fs = int(snd.samplerate()) silences = detect_silences(rms, fs) head, tail = os.path.split(wav) tail = os.path.splitext(tail)[0] tail = tail + "_silence.npy" silence_filepath = os.path.join(outDir, tail) np.save(silence_filepath, silences)
def generate_audio_stimulus(MatrixDir, OutDir, indexes, socketio=None): # Get matrix wav file paths wavFiles = globDir(MatrixDir, '*.wav') wavFileMatrix = organiseWavs(wavFiles) wav_dir = os.path.join(args['OutDir'], "wav") dir_must_exist(wav_dir) sentence_dir = os.path.join(wav_dir, "sentence-lists") dir_must_exist(sentence_dir) # Synthesize audio for each trial using generated word choices sentence_lists = {} for key in indexes.keys(): files = [] list_dir = os.path.join(sentence_dir, key) dir_must_exist(list_dir) with open(os.path.join(list_dir, 'stim_parts.csv'), 'w') as csvfile: partwriter = csv.writer(csvfile) inds, strings = indexes[key] for sentence_ind, (component_inds, component_strings) in enumerate( zip(inds, strings)): if socketio: percent = (l / Length) * 100. socketio.emit('update-progress', {'data': '{}%'.format(percent)}, namespace='/main') y, wavInfo, partnames = synthesize_trial( wavFileMatrix, component_inds) partwriter.writerow(component_strings) file_name = os.path.join( list_dir, 'Trial_{0:05d}.wav'.format(sentence_ind + 1)) sndio.write(file_name, y, **wavInfo) files.append(file_name) sentence_lists[key] = np.array(files) return sentence_lists
def gen_audio_stim(MatrixDir, OutDir, indexes): if os.path.exists(OutDir): shutil.rmtree(OutDir) os.makedirs(OutDir) wavFiles = globDir(MatrixDir, '*.wav') wavFileMatrix = organiseWavs(wavFiles) wavDir = os.path.join(OutDir, "wav") dir_must_exist(wavDir) wavDir = os.path.join(wavDir, "noise-sentences") dir_must_exist(wavDir) files = [] n = 0 o = 0 for sentenceList in indexes: n += 1 o = 0 files.append([]) for ind in sentenceList: o += 1 y, wavInfo, partnames = synthesize_trial(wavFileMatrix, ind) fileName = os.path.join(wavDir, 'Trial_{0:02d}_{1:02d}.wav'.format(n, o)) print("Generating: " + fileName) sndio.write(fileName, y, **wavInfo) files[-1].append(fileName) return files
def main(): word_files = globDir("./out/stim/", "stim_words_*.csv") q_files = [x.replace("word", "question") for x in word_files] for word_file, q_file in zip(word_files, q_files): with open(word_file, 'r') as wordfile, open(q_file, 'w') as qfile: wordreader = csv.reader(wordfile) qwriter = csv.writer(qfile) sentences = [line for line in wordreader] n_sentences = len(sentences) q1_population = sentences[:n_sentences // 2] q2_population = sentences[n_sentences // 2:] q1 = random.choice(q1_population) q2 = random.choice(q2_population) blank_ind1 = random.randint(0, len(q1) - 1) q1_ans = q1[blank_ind1] q1[blank_ind1] = '_' blank_ind2 = random.randint(0, len(q2) - 1) q2_ans = q2[blank_ind2] q2[blank_ind2] = '_' q1 = [" ".join(q1), q1_ans] q2 = [" ".join(q2), q2_ans] qwriter.writerows([q1, q2])
def calc_potential_max(stim_folder, noise_filepath, out_dir): max_wav_samp = 0 max_wav_rms = 0 wavs = globDir(stim_folder, '*.wav') 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))]) 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)) 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 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, "reduction_coef.npy"), reduction_coef)
def generateAudioStimulus(MatrixDir, OutDir, Length, indexes, socketio=None): # Get matrix wav file paths wavFiles = globDir(MatrixDir, '*.wav') wavFileMatrix = organiseWavs(wavFiles) with open(os.path.join(OutDir, 'stim_parts.csv'), 'w') as csvfile: partwriter = csv.writer(csvfile) # Synthesize audio for each trial using generated word choices l = 0 n = 0 files = [] while l < Length: if socketio: percent = (l / Length) * 100. socketio.emit('update-progress', {'data': '{}%'.format(percent)}, namespace='/main') #print("Generating Trial_{0:05d}".format(n)) y, wavInfo, partnames = synthesizeTrial(wavFileMatrix, indexes[n, :]) partwriter.writerow(partnames) fileName = os.path.join(OutDir, 'Trial_{0:05d}.wav'.format(n)) pysndfile.sndio.write(fileName, y, **wavInfo) n += 1 l += y.size / wavInfo['rate'] files.append(fileName) return files
def gen2(MatrixDir, OutDir, indexes): wavFiles = globDir(MatrixDir, '*.wav') wavFileMatrix = organiseWavs(wavFiles) files = [] for sentenceList in indexes: for ind in sentenceList: y, wavInfo, partnames = synthesizeTrial(wavFileMatrix, ind)
def generateNoiseFromSentences(SentenceDir, OutDir, order=500, plot=False, socketio=None): ''' Fit speech shaped noise to all wav files found in SentenceDir. Output speech shaped noise of a length equal to the combined length of all found audio in SentenceDir to OutDir. ''' wavFiles = globDir(SentenceDir, '*.wav') data = [] for path in wavFiles: audio, fs, enc, fmt = pysndfile.sndio.read(path, return_format=True) # Add add silence after each clip silenceLen = int(0.1 * fs) silence = np.zeros(silenceLen) chunk = np.append(audio, silence) data.append(chunk) x = np.concatenate(data) y = processNoise(x, order=order, plot=plot, fs=fs) noiseFile = os.path.join(OutDir, 'SSN.wav') print("Writing file...") pysndfile.sndio.write(os.path.join(OutDir, 'SSN.wav'), y, rate=fs, format=fmt, enc=enc) return noiseFile
def main(): wavs = globDir('./out/stim/', '*.wav') envs = globDir('./out/stim/', 'stim_*_env.npy') silences = globDir('./out/stim/', 'stim_*_silence.npy') for wavfp, envfp, silfp in zip(wavs, envs, silences): snd = PySndfile(wavfp, 'r') fs = int(snd.samplerate()) env = np.load(envfp) sil_slices = np.load(silfp) sil = np.zeros(env.size) for sil_slice in sil_slices: sil[sil_slice[0]:sil_slice[1]] = 1 pdb.set_trace() plt.plot(snd.read_frames(fs*60)) plt.plot(sil[:fs*60]) plt.show()
def main(): wavs = globDir('./out/stim/', '*.wav') silences = globDir('./out/stim/', 'stim_*_silence.npy') outDir = "./out/stim/" for wav, sil in zip(wavs, silences): snd = PySndfile(wav, 'r') fs = int(snd.samplerate()) s = np.load(sil) sil_bool = slice_to_bool(s, snd.frames()) rms = np.sqrt(np.mean(np.abs(snd.read_frames()[~sil_bool]**2))) head, tail = os.path.split(wav) tail = os.path.splitext(tail)[0] tail = tail + "_rms.npy" rms_filepath = os.path.join(outDir, tail) np.save(rms_filepath, rms)
def main(): wavs = globDir('./', 'stim.wav') for wav in wavs: out_filepath = "{0}_old{1}".format(head, tail) out_temppath = "{0}_temp{1}".format(head, tail) os.rename(wav, out_temppath) os.rename(out_filepath, wav) os.rename(out_temppath, out_filepath)
def main(): wavs = globDir('./', 'stim.wav') for wav in wavs: x, fs, enc, fmt = sndio.read(wav, return_format=True) y = x[:, :2] head, tail = os.path.splitext(wav) out_filepath = "{0}_old{1}".format(head, tail) os.rename(wav, out_filepath) sndio.write(wav, y, rate=fs, format=fmt, enc=enc)
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)
def main(): ''' ''' wavs = globDir("./stimulus", "*.wav") for wav in wavs: x, fs, enc, fmt = sndio.read(wav, return_format=True) 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 wav_out = os.path.splitext(wav)[0] + "_trig.wav" sndio.write(wav_out, y, rate=fs, format=fmt, enc=enc)
def generateDecoderAudio(SentenceDir, NoiseDir, OutDir, n_splits=8): ''' Generate stimulus for training decoder at set SNRs using previous synthesized matrix test audio and spech shaped noise. ''' n_splits = float(n_splits) wavFiles = globDir(SentenceDir, '*.wav') data = [] markers = [] i = 0 for path in wavFiles: audio, fs, enc, fmt = pysndfile.sndio.read(path, return_format=True) silenceLen = int(0.1 * fs) silence = np.zeros(silenceLen) chunk = np.append(audio, silence) data.append(chunk) markers.append(i) i += chunk.size markers = np.array(markers) split_size = i / n_splits splits = np.arange(n_splits) * split_size idx = find_nearest(markers, splits) idx = np.append(idx, len(data)) idx = rolling_window_lastaxis(idx, 2) splitData = [] for start, end in idx: splitData.append(np.concatenate([data[x] for x in range(start, end)])) x, fs, enc, fmt = pysndfile.sndio.read(os.path.join(NoiseDir, 'SSN.wav')) noiseData = [] for start, end in idx: noiseData.append(x[start:end]) pdb.set_trace() snr = 20 * np.log10( np.sqrt(np.mean(signal**2)) / np.sqrt(np.mean(noise**2)))
'matrix test materials') parser.add_argument('--OutDir', type=PathType(exists=None, type='dir'), default='./noise', help='Output directory') parser.add_argument('--CalcRMS', action='store_true') args = { k: v for k, v in vars(parser.parse_args()).items() if v is not None } rmsDir = os.path.join(args['OutDir'], "rms") dir_must_exist(rmsDir) peakDir = os.path.join(args['OutDir'], "peak") dir_must_exist(peakDir) wavDir = os.path.join(args['OutDir'], "wav") dir_must_exist(wavDir) if args['CalcRMS']: daFile = globDir('./noise_source', 'male_speech_resamp.wav')[0] rmsFiles, peakFiles = gen_rms_peak([daFile], rmsDir, peakDir) rmsFile = rmsFiles[0] peakFile = peakFiles[0] else: daFile = globDir('./noise_source', 'male_speech_resamp.wav')[0] rmsFile = globDir(rmsDir, '*.npy')[0] peakFile = globDir(peakDir, '*.npy')[0] #silences = detect_silences([rmsFile], 44100, None) s_rms = calc_speech_rms(['./stimulus/3000_da.wav'], [[]], rmsDir) b = calc_spectrum([daFile], [np.array([])]) y = gen_noise(args['OutDir'], b, 44100, s_rms)
def main(): stim_dir = "../behavioural_stim/stimulus" wav_dir = "../behavioural_stim/stimulus/wav" base_dir = "../behavioural_stim/stimulus/wav/sentence-lists/" noise_dir = "../behavioural_stim/stimulus/wav/noise/" out_dir = "./out" dir_must_exist(base_dir) dir_must_exist(out_dir) dir_must_exist(wav_dir) dir_must_exist(noise_dir) noise_filepath = "../behavioural_stim/stimulus/wav/noise/noise_norm.wav" folders = os.listdir(base_dir) folders = natsorted(folders)[1:15] folders = list(zip(folders[::2], folders[1::2])) calc_potential_max(base_dir, noise_filepath, out_dir) n_questions = 4 fs = 44100 for ind, (list_folder_1, list_folder_2) in enumerate(folders): out_folder_name = 'Stim_{}'.format(ind) out_folder = os.path.join(out_dir, out_folder_name) delete_if_exists(out_folder) dir_must_exist(out_folder) out_wav_path = os.path.join(out_folder, "stim.wav") out_csv_path = os.path.join(out_folder, "markers.csv") out_rms_path = os.path.join(out_folder, "rms.npy") out_q_path = [ os.path.join(out_folder, "questions_{}.csv".format(x)) for x in range(n_questions) ] out_wav = PySndfile(out_wav_path, 'w', construct_format('wav', 'pcm16'), 3, 44100) list_1_wav = globDir(os.path.join(base_dir, list_folder_1), '*.wav') list_2_wav = globDir(os.path.join(base_dir, list_folder_2), '*.wav') list_1_csv = globDir(os.path.join(base_dir, list_folder_1), '*.csv') list_2_csv = globDir(os.path.join(base_dir, list_folder_2), '*.csv') merged_wavs = list_1_wav + list_2_wav merged_csvs = list_1_csv + list_2_csv words = [] for c in merged_csvs: with open(c, 'r') as csvfile: for line in csv.reader(csvfile): words.append(line) c = list(zip(merged_wavs, words)) shuffle(c) merged_wavs, words = zip(*c) sum_sqrd = 0. n = 0 with open(out_csv_path, 'w') as csvfile, ExitStack() as stack: # Open all question files qfiles = [ stack.enter_context(open(qfile, 'w')) for qfile in out_q_path ] writer = csv.writer(csvfile) qwriters = [csv.writer(qfile) for qfile in qfiles] counter = 0 stim_count = len(merged_wavs) stim_count_half = stim_count // 2 q_inds = np.array([ sample(range(0, stim_count_half), n_questions), sample(range(stim_count_half, stim_count - 1), n_questions) ]).T a = 0 silence = np.zeros((88200, 3)) idx = np.arange(0, silence.shape[0]) trigger = gen_trigger(idx, 2., 0.01, fs) silence[:, 2] = trigger out_wav.write_frames(silence) for ind, (wav, txt) in enumerate(zip(merged_wavs, words)): csv_line = [counter] silence = np.zeros((int( np.random.uniform(int(0.3 * 44100), int(0.4 * 44100), 1)), 3)) idx = np.arange(counter, counter + silence.shape[0]) trigger = gen_trigger(idx, 2., 0.01, fs) silence[:, 2] = trigger out_wav.write_frames(silence) counter += silence.shape[0] csv_line.append(counter) csv_line.append("#") writer.writerow(csv_line) csv_line = [counter] x, fs, enc = sndio.read(wav) sum_sqrd += np.sum(x**2) n += x.size y = np.vstack([x, x, np.zeros(x.size)]).T idx = np.arange(counter, counter + y.shape[0]) trigger = gen_trigger(idx, 2., 0.01, fs) y[:, 2] = trigger out_wav.write_frames(y) counter += y.shape[0] csv_line.append(counter) csv_line.append(" ".join(txt)) writer.writerow(csv_line) if ind in q_inds: writer_ind = int(np.where(ind == q_inds)[0]) blank_ind = randint(0, len(txt) - 1) q_list = copy(txt) q_list[blank_ind] = '_' qwriters[writer_ind].writerow( [" ".join(q_list), txt[blank_ind]]) a += 1 if a != 8: pdb.set_trace() csv_line = [counter] silence = np.zeros( (int(np.random.uniform(int(0.3 * 44100), int(0.4 * 44100), 1)), 3)) idx = np.arange(counter, counter + silence.shape[0]) trigger = gen_trigger(idx, 2., 0.01, fs) silence[:, 2] = trigger out_wav.write_frames(silence) counter += silence.size csv_line.append(counter) csv_line.append("#") writer.writerow(csv_line) rms = np.sqrt(sum_sqrd / n) np.save(out_rms_path, rms) x, fs, enc = sndio.read(out_wav_path)
type=PathType(exists=None, type='dir'), default='./stimulus', help='Output directory') parser.add_argument('--CalcRMS', action='store_true') args = { k: v for k, v in vars(parser.parse_args()).items() if v is not None } rmsDir = os.path.join(args['OutDir'], "rms") if args['CalcRMS']: indexes = gen_indexes() wavFiles = gen_audio_stim(args['MatrixDir'], args['OutDir'], indexes) rmsFiles = gen_rms(wavFiles, rmsDir) else: wavDir = os.path.join(args['OutDir'], "wav") dir_must_exist(wavDir) wavFiles = globDir(wavDir, '*.wav') wf = [] for listInd in range(50): wf.append([]) for sentenceInd in range(10): wf[listInd].append(wavFiles[listInd * 10 + sentenceInd]) wavFiles = wf rmsFiles = globDir(rmsDir, 'Trial*.npy') 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)
def main(): wavs = globDir('./out/stim/', '*.wav') args = [(x, "./out/stim/") for x in wavs] multiprocess_map(gen_rms, args)