Reconstructing high-dimensional representations of tinnitus using reverse correlation and compressed sensing.
For most users, it is best to install the MATLAB toolbox from the latest Release. For development, clone the following projects:
- mtools
- tinnitus-reconstruction
- ReadYAML (only for legacy use)
- yaml
Then add the functions to your path. The commands should look similar to this:
addpath ~/code/yaml
addpath ~/code/srinivas.gs_mtools/src
savepath
Finally, in the tinnitus-reconstruction/code
directory,
run setup.m
as a MATLAB script.
Install the latest Release.
There are multiple experiments available in this repository.
All experiments can be found in the tinnitus-reconstruction/code/experiment/Protocols
directory.
The published, novel experimental protocol is in RevCorr.m
.
To run any experiment, copy the template configuration file found here and modify it as you see fit.
Then, using a decibel meter (many are available for smartphones), record the decibel output through the headphones of sound that plays after running the following function:
play_calibration_sound()
Raise your system volume until the measured dB value is above 95dB.
Save this value in the MATLAB workspace. For example cal_dB = 97.8;
Don't worry, no sounds will be played above 65 dB unless made to do so by the user.
Then, run any of the Protocol functions with this measured dB value in your MATLAB prompt.
ThresholdDetermination(cal_dB)
LoudnessMatch(cal_dB)
PitchMatch(cal_dB)
RevCorr(cal_dB)
The function RunAllExp(cal_dB)
uses one config file
to run the protocol functions in the above order, repeating PitchMatch 3
times by default.
To inspect reverse correlation results from AX (template sound) experiments, run:
pilot_reconstruction
reconstruction_viz
Use patient_reconstructions
to inspect results from non-AX experiments.
Data can be collected from the other protocols by running
collect_data_pitch_match()
collect_data_thresh_or_loud()
An experiment is specified by a configuration file.
These are YAML file that generally live in tinnitus-reconstruction/code/experiment/configs/
,
but you can put them anywhere.
A template config file can be found here. This template file includes inline comments that describe a sample configuration file and what fields are available.
In brief, the following fields are required to run a reverse correlation experiment:
- stimuli_type
- n_trials_per_block
- n_blocks
- subjectID
To run a threshold determination, loudness matching, or pitch matching experiment, the following two fields are additionally required.
- min_tone_freq
- max_tone_freq
Note: stimuli_type
, n_trials_per_block
, and n_blocks
have no effect on non-reverse correlation protocols, but are still required to exist in a config file.
Similarly, min_tone_freq
and max_tone_freq
do not interact with reverse correlation protocols and are not required in a config file.
Other config fields include:
- data_dir: path to directory where output files from the experiment should be saved
- stimuli_save_type: either
waveform
,spectrum
, orbins
. Determines in what form data from the experiment should be saved. - various stimuli parameters including:
- min_freq: the minimum frequency (in Hz) of the stimuli
- max_freq: the maximum frequency (in Hz) of the stimuli
- n_bins: how many tonotopic bins the stimuli has
- duration: the duration of the stimuli (in seconds)
- stimuli hyperparameters specific to each stimulus generation type (see the stimuli class definitions for details)
You can load a config file into memory:
config = parse_config('path/to/config_file.yaml');
and generate a stimulus generation object from the config:
stimgen = eval([char(config.stimuli_type), 'StimulusGeneration()']);
To set parameters in a stimulus generation object, use the from_config()
method,
which takes a path or a config struct:
stimgen = GaussianPriorStimulusGeneration();
stimgen = stimgen.from_config('path/to/config_file.yaml'); % stimgen.from_config(config);
You can generate a serialized experiment ID via:
expID = get_experiment_ID(config);
Or a hash via:
this_hash = get_hash(config);
Stimulus generation classes are defined here.
All stimulus generation classes inherit from AbstractStimulusGenerationMethod
.
Non-binned classes inherit directly
and binned classes through the intermediate class AbstractBinnedStimulusGeneratioMethod
.
This class defines common properties of all stimulus generation methods.
They are described here in brief with default values, e.g., property_name = default_value
.
They include:
min_freq = 100
: the minimum frequency of stimuli generated by this method (Hz).max_freq = 22000
: the maximum frequency of stimuli generated by this method (Hz).duration = 0.5
: the duration of stimuli generation by this method (seconds).n_trials = 100
: the number of trials in a single block.Fs = 44100
: the sample frequency of the stimuli generated by this method (samples/sec).nfft = duration*Fs
: Dependant property, the number of fast Fourier transform points.
Methods:
[y, spect, binned_repr] = subject_selection_process(self, signal)
[stimuli_matrix, Fs, spect_matrix, binned_repr_matrix] = generate_stimuli_matrix(self)
freq = get_freq(self)
self = from_config(self, options)
stim = synthesize_audio(X, nfft)
This abstract class includes three additional properties:
n_bins = 100
: The number of bins to use to represent the frequency axis.unfilled_dB = -100
: The value of a bin labeled "unfilled" (dB).filled_dB = 0
: The value of a bin labeled "filled" (dB)
Methods:
[y, spect, binned_repr] = subject_selection_process(self,representation)
[binnum, Fs, nfft, frequency_vector] = get_freq_bins(self)
spect = get_empty_spectrum(self)
binned_repr = spect2binnedrepr(self, T)
T = binnedrepr2spect(self, binned_repr)
[wav, X, binned_rep] = binnedrepr2wav(self, binned_rep, mult, binrange, new_n_bins, options)
W = bin_signal(self, W, Fs)
Any StimulusGeneration
class such as GaussianPriorStimulusGeneration
includes the generate_stimulus
method.
[stim, Fs, X, binned_repr] = generate_stimulus(self)
The RevCorr
, ThresholdDetermination
, LoudnessMatch
, and PitchMatch
functions run an experiment. You can invoke any of them in two ways:
RevCorr(cal_dB)
RevCorr(cal_dB, 'config', 'path_to_config_file')
In the first case, a dialog box opens and asks you to select a .yaml
config file.
In the second case, you specify the path to a config file directly.
The cal_dB
parameter is described above.
Data are saved in config.data_dir
which is usually
tinnitus-reconstruction/code/experiment/Data
.
For RevCorr
, each block has a separate stimuli and response file saved for it,
labeled by the subject ID and a unique hash.
For the other experiments, each experiment has separate stimuli and responses saved and similarly marked.
You can use the collect_data
functions to gather the data into output matrices.
[responses, stimuli] = collect_data('config', 'path_to_config_file');
[responses, stimuli, octave_responses, octave_stimuli] = collect_data_pitch_match('config', 'path_to_config_file')
[dBs, tones] = collect_data_thresh_or_loud('loudness', 'config', 'path_to_config_file')
[dBs, tones] = collect_data_thresh_or_loud('threshold', 'config', 'path_to_config_file')
You can use compressed sensing (cs
), compressed sensing without a basis (cs_no_basis
), linear regression (gs
) or ridge regression (gs('ridge',true)
).
To generate a reconstruction with one of these methods, pass it as a name-value argument with 'method':
[x, responses_output, stimuli_matrix_output] = get_reconstruction('config', config, 'method', 'cs');
[x, responses_output, stimuli_matrix_output] = get_reconstruction('config', config, 'method', 'linear');
[x, responses_output, stimuli_matrix_output] = get_reconstruction('config_file', 'path/to/config/file.yaml', 'method', 'cs_ridge');
[x, responses_output, stimuli_matrix_output] = get_reconstruction('config_file', 'path/to/config/file.yaml', 'method', 'linear_ridge');
@article{Hoyland2023,
author={Hoyland, Alec and Barnett, Nelson V. and Roop, Benjamin W. and Alexandrou, Danae and Caplan, Myah and Mills, Jacob and Parrell, Benjamin and Chari, Divya A. and Lammert, Adam C.},
journal={IEEE Open Journal of Engineering in Medicine and Biology},
title={Reverse Correlation Uncovers More Complete Tinnitus Spectra},
year={2023},
volume={4},
number={},
pages={116-118},
doi={10.1109/OJEMB.2023.3275051}
}