You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: getWaveformsFromDat.m
    path of file: ./repos/CellExplorer/calc_CellMetrics
    
    the code of the file until where you have to start completion: function spikes = getWaveformsFromDat(spikes,session,varargin)
% Extracts raw waveforms from the binary file. 
% This function is part of CellExplorer: https://cellexplorer.org/
%
% INPUTS
% Spikes struct:            https://cellexplorer.org/datastructure/data-structure-and-format/#spikes
% session metadata struct:  https://cellexplorer.org/datastructure/data-structure-and-format/#session-metadata
%
% Last edited: 21-12-2020

% Loading preferences
preferences = preferences_ProcessCellMetrics(session);

p = inputParser;
addParameter(p,'unitsToProcess',1:size(spikes.times,2), @isnumeric);
addParameter(p,'nPull',preferences.waveform.nPull, @isnumeric); % number of spikes to pull out (default: 600)
addParameter(p,'wfWin_sec', preferences.waveform.wfWin_sec, @isnumeric); % Larger size of waveform windows for filterning. total width in seconds (default: 0.004)
addParameter(p,'wfWinKeep', preferences.waveform.wfWinKeep, @isnumeric); % half width in seconds (default: 0.0008)
addParameter(p,'showWaveforms', true, @islogical);
addParameter(p,'filtFreq',[500,8000], @isnumeric); % Band pass filter (default: 500Hz - 8000Hz)

    
function spikes = getWaveformsFromDat(spikes,session,varargin)
% Extracts raw waveforms from the binary file. 
% This function is part of CellExplorer: https://cellexplorer.org/
%
% INPUTS
% Spikes struct:            https://cellexplorer.org/datastructure/data-structure-and-format/#spikes
% session metadata struct:  https://cellexplorer.org/datastructure/data-structure-and-format/#session-metadata
%
% Last edited: 21-12-2020

% Loading preferences
preferences = preferences_ProcessCellMetrics(session);

p = inputParser;
addParameter(p,'unitsToProcess',1:size(spikes.times,2), @isnumeric);
addParameter(p,'nPull',preferences.waveform.nPull, @isnumeric); % number of spikes to pull out (default: 600)
addParameter(p,'wfWin_sec', preferences.waveform.wfWin_sec, @isnumeric); % Larger size of waveform windows for filterning. total width in seconds (default: 0.004)
addParameter(p,'wfWinKeep', preferences.waveform.wfWinKeep, @isnumeric); % half width in seconds (default: 0.0008)
addParameter(p,'showWaveforms', true, @islogical);
addParameter(p,'filtFreq',[500,8000], @isnumeric); % Band pass filter (default: 500Hz - 8000Hz)
addParameter(p,'keepWaveforms_filt', false, @islogical); % Keep all extracted filtered waveforms
addParameter(p,'keepWaveforms_raw', false, @islogical); % Keep all extracted raw waveforms
addParameter(p,'saveFig', false, @islogical); % Save figure with data
addParameter(p,'saveMat', true, @islogical); % Save figure with data
addParameter(p,'extraLabel', '', @ischar); % Extra labels in figures
addParameter(p,'getBadChannelsFromDat', true, @islogical); % Determining any extra bad channels from noiselevel of .dat file

parse(p,varargin{:})

wfWin_sec = p.Results.wfWin_sec;
wfWinKeep = p.Results.wfWinKeep;
keepWaveforms_filt = p.Results.keepWaveforms_filt;
keepWaveforms_raw = p.Results.keepWaveforms_raw;
params = p.Results;

% Loading session struct into separate parameters
basepath = session.general.basePath;
basename = session.general.name;
LSB = session.extracellular.leastSignificantBit;
nChannels = session.extracellular.nChannels;
sr = session.extracellular.sr;
electrodeGroups = session.extracellular.electrodeGroups.channels;
nElectrodeGroups = session.extracellular.nElectrodeGroups;
if isfield(session.extracellular,'fileName') && ~isempty(session.extracellular.fileName)
    fileNameRaw = session.extracellular.fileName;
else
    fileNameRaw = [basename '.dat'];
end