Commit fa017052 authored by Jan-Gerrit Richter's avatar Jan-Gerrit Richter

Merge branch 'master' of https://git.rwth-aachen.de/ita/toolbox

parents ce202ccb 576d72e1
......@@ -106,7 +106,7 @@ ear_d = [-0.07 0.07];
W = sparse(diag(w)); % diagonal matrix containing weights
D = sparse(diag(dweights_rep)); % decomposition order-dependent Tikhonov regularization
Y = ita_sph_base(this.dirCoord,Nmax,'orthonormal',false); % calculate real-valued SHs using the measurement grid
Y = ita_sph_base(this.dirCoord,Nmax,'real'); % calculate real-valued SHs using the measurement grid
%% Calculate HRTF data for field points
if Nmax > 25
......@@ -131,7 +131,7 @@ for ear=1:2
% % calculate weighted SH coefficients using a decomposition order-dependent Tikhonov regularization
%
% freqData_temp = data.freqData;
% Y = ita_sph_base(data.channelCoordinates,Nmax,'orthonormal',false);
% Y = ita_sph_base(data.channelCoordinates,Nmax,'real');
a0 = (Y.'*W*Y + epsilon*D) \ Y.'*W * freqData_temp.';
%a0 = (Y.'*W*Y + epsilon*D) \ Y.' *
......@@ -142,10 +142,10 @@ for ear=1:2
% calculate range-extrapolated HRTFs
a1 = a0 .* hankel_rep.';
Yest = ita_sph_base(field,N,'orthonormal',false); % use real-valued SH's
Yest = ita_sph_base(field,N,'real'); % use real-valued SH's
hrtf_arbi(:,ear:2:end) = (Yest*a1).'; % interpolated + range-extrapolated HRTFs
else
Yest = ita_sph_base(field,Nmax,'orthonormal',false); % use real-valued SH's
Yest = ita_sph_base(field,Nmax,'real'); % use real-valued SH's
hrtf_arbi(:,ear:2:end) = (Yest*a0).'; % interpolated HRTFs
end
end
......
......@@ -1110,7 +1110,7 @@ classdef itaHRTF < itaAudio
W = diag(vWeights); % diagonal matrix containing weights
D = diag(regweights_rep); % decomposition order-dependent Tikhonov regularization
Y = ita_sph_base(this.dirCoord,Nmeas,'orthonormal',false); % calculate real-valued SHs using the measurement grid (high SH-order)
Y = ita_sph_base(this.dirCoord,Nmeas,'real'); % calculate real-valued SHs using the measurement grid (high SH-order)
%% Calculate spatially smoothed HRTF data set
hrtf_smoo_wo_ITD = zeros(this.nBins,2*this.dirCoord.nPoints); % init.: columns: LRLRLR...
......@@ -1302,11 +1302,11 @@ classdef itaHRTF < itaAudio
earSidePlot = sArgs.earSide;
if numel(phiC_deg)>1,
xData = phiC_deg;
strTitle =[ earSidePlot ' ear, \theta = ' num2str(round(thetaC_deg)) ''];
strTitle =[ earSidePlot ' ear, \theta = ' num2str(round(thetaC_deg)) ''];
strXlabel = '\phi in Degree';
else
xData = thetaC_deg;
strTitle =[earSidePlot ' ear, \phi = ' num2str(round(phiC_deg)) ''];
strTitle =[earSidePlot ' ear, \phi = ' num2str(round(phiC_deg)) ''];
strXlabel = '\theta in Degree';
end
......@@ -1394,11 +1394,11 @@ classdef itaHRTF < itaAudio
earSidePlot = sArgs.earSide;
if numel(phiC_deg)>1,
xData = phiC_deg;
strTitle =[ earSidePlot ' ear, \theta = ' num2str(round(thetaC_deg)) ''];
strTitle =[ earSidePlot ' ear, \theta = ' num2str(round(thetaC_deg)) ''];
strXlabel = '\phi in Degree';
else
xData = thetaC_deg;
strTitle =[earSidePlot ' ear, \phi = ' num2str(round(phiC_deg)) ''];
strTitle =[earSidePlot ' ear, \phi = ' num2str(round(phiC_deg)) ''];
strXlabel = '\theta in Degree';
end
......
......@@ -6,7 +6,7 @@ function [ data, samplerate, metadata ] = dfitaHRIRDAFFDataFunc( alpha, beta, it
% DAFF requires data alignment by multiple of 4
nResidual = mod( hrtf.nSamples, 4 );
data = [ hrtf.timeData', zeros( hrtf.nChannels, 4 - nResidual ) ];
data = [ hrtf.timeData', zeros( hrtf.nChannels, mod(4 - nResidual,4) ) ];
metadata = [];
end
......@@ -44,26 +44,33 @@ end
theta_start_deg = rad2deg( min( this.channelCoordinates.theta ) );
theta_end_deg = rad2deg( max( this.channelCoordinates.theta ) );
theta_num_elements = size( unique( this.channelCoordinates.theta ), 1 );
theta_num_elements = size( uniquetol( this.channelCoordinates.theta ), 1 );
phi_start_deg = rad2deg( min( mod( this.channelCoordinates.phi, 2*pi ) ) );
phi_end_deg = rad2deg( max( mod( this.channelCoordinates.phi, 2*pi ) ) );
phi_num_elements = size( unique( this.channelCoordinates.phi ), 1 );
phi_start_deg = rad2deg( min( mod( this.channelCoordinates.phi, 2 * pi ) ) );
phi_end_deg = rad2deg( max( mod( this.channelCoordinates.phi, 2 * pi ) ) );
phi_num_elements = size( uniquetol( this.channelCoordinates.phi ), 1 );
assert( phi_num_elements ~= 0 );
alphares = ( phi_end_deg - phi_start_deg ) / phi_num_elements; % phi end does not cover entire circle in this case
alphares_full_circle = ( phi_end_deg - phi_start_deg ) / ( phi_num_elements - 1 ); % phi end does not cover entire circle in this case
if phi_end_deg + alphares_full_circle >= 360.0
alpharange = [ phi_start_deg ( phi_end_deg + alphares_full_circle ) ]; % Account for full circle
alpharange = [ phi_start_deg 360 ]; % Account for full circle and force end of range to 360 deg
alphares = alphares_full_circle;
else
alpharange = [ phi_start_deg phi_end_deg ];
end
assert( alpharange( 1 ) >= 0.0 )
assert( alpharange( 2 ) <= 360.0 )
assert( theta_num_elements ~= 0 );
betares = ( theta_end_deg - theta_start_deg ) / ( theta_num_elements - 1 ); % phi end does not cover entire circle
betarange = 180 - [ theta_start_deg theta_end_deg ]; % Flip poles (DAFF starts at south pole)
assert( betarange( 2 ) >= 0.0 )
assert( betarange( 1 ) <= 180.0 )
%% Assemble metadata
metadata = daffv17_add_metadata( metadata, 'Generation script', 'String', 'writeDAFFFile.m' );
......
......@@ -14,6 +14,7 @@ classdef itaHpTF_Audio < itaHpTF
% Audio Engineering Society Convention 130, May 2011)
% normalized (Normalization of HpTF)
% smoothing (Smoothing bandwidth has to be defined in fractions of octaves, see also ita_smooth)
% mic (measured microphone transfer funcions - not inverted: length does not matter; will be adapted)
%
% itaHpTF_Audio Methods (private):
% HP_equalization If this.mic is not set, it will be unused
......@@ -30,7 +31,9 @@ classdef itaHpTF_Audio < itaHpTF
m_fUpper = 18000;
mMethod = 'mSTD';
mNormalized = true;
mGainComp = true;
mSmoothing = 1/6;
mSelectMeas = 1:8; % select the channels which should be used for the HpTF
end
properties(Dependent = true, Hidden = false)
......@@ -38,8 +41,10 @@ classdef itaHpTF_Audio < itaHpTF
fLower = 100;
fUpper = 18000;
method = 'mSTD';
normalized = true;
normalized = true; % normalization of the signal
gainComp = true; % microphone compensation
smoothing = 1/6;
selectMeas = 1:8; % select specific measurements
end
properties (Dependent = true, SetAccess = private)
......@@ -122,6 +127,13 @@ classdef itaHpTF_Audio < itaHpTF
function normalized = get.normalized(this)
normalized = this.mNormalized; end
function comp = get.gainComp(this)
comp = this.mGainComp; end
function sel = get.selectMeas(this)
sel = this.mSelectMeas; end
function smoothing = get.smoothing(this)
smoothing = this.mSmoothing; end
%% ................................................................
......@@ -151,6 +163,16 @@ classdef itaHpTF_Audio < itaHpTF
this = HP_equalization(this);
end
function this = set.selectMeas(this,ch)
this.mSelectMeas = ch;
this = HP_equalization(this);
end
function this = set.gainComp(this,comp)
this.mGainComp = comp;
this = HP_equalization(this);
end
function this = set.smoothing(this,smoothing)
this.mSmoothing = smoothing;
this = HP_equalization(this);
......@@ -162,11 +184,12 @@ classdef itaHpTF_Audio < itaHpTF
% SET PRIVATE
%..................................................................
function this = set.init(this,var)
this.nameHP = var.nameHP;
this.nameHP = var.nameHP;
this.nameMic = var.nameMic;
this.nameSubj = var.nameSubj;
this.repeat = var.repeat;
this.mTF.time = var.time;
this.selectMeas = 1:var.repeat;
this = HP_equalization(this);
end
......@@ -175,11 +198,8 @@ classdef itaHpTF_Audio < itaHpTF
% Audio Engineering Society Convention 130, May 2011
tWin = this.TF.trackLength; % crop HPTF
if this.mic.dimensions == 2 % mic min phase + extension
minMic = ita_minimumphase(this.mic);
[mic, TF] = ita_extend_dat(minMic,this.TF);
else TF = this.TF;
end
measSel = sort([2*this.selectMeas-1 2*this.selectMeas]);
TF = this.TF.ch(measSel);
%init
thisEQ = this;
......@@ -200,14 +220,19 @@ classdef itaHpTF_Audio < itaHpTF
otherwise
error('Unknown type');
end
if this.mic.dimensions == 2
Rec = ita_multiply_spk(Rec,mic);
if this.mic.dimensions == 2 % Compensation of mic
minMic = ita_minimumphase(this.mic);
RecM = ita_convolve(Rec,minMic.ch(cdx));
RecM.fftDegree = TF.fftDegree;
else
RecM = Rec;
end
%% Short Filter with no correction for low freqs and minimun phase
aux = max(abs(Rec.freqData),[],2);
%% Short Filter with no correction for low freqs and minimum phase
aux = max(abs(RecM.freqData),[],2);
% find first maximum and truncate low freq correction at this point
idxDF = Rec.freq2index([this.fLower this.fLower*1.5 ]);
idxDF = RecM.freq2index([this.fLower this.fLower*1.5 ]);
d_aux = diff(aux(idxDF(1):idxDF(2)));
idx = find(diff(sign(d_aux)) ~= 0,1,'first'); % Bruno style...
aux(1:idxDF(1)+idx+1) = aux(idxDF(1)+idx+2);
......@@ -227,10 +252,18 @@ classdef itaHpTF_Audio < itaHpTF
this_min = ita_minimumphase(ita_time_shift(HpTF,tWin/2));
this_win = ita_time_window(this_min,[tWin*0.99,tWin],'time','crop');
if this.normalized,
this_norm = ita_normalize_dat(this_win);
if this.gainComp % compensate gains from mics (equalize)
idxDF = this_win.freq2index(this.fLower);
chGain = 20*log10(abs(this_win.freqData(idxDF,:)));
this_comp = this_win;
this_comp.freqData = bsxfun(@times,this_win.freqData,10.^(-chGain/20));
else, this_comp = this_win;
end
if this.normalized
this_norm = ita_normalize_dat(this_comp);
thisEQ.timeData = this_norm.timeData;
else thisEQ.timeData = this_win.timeData;
else, thisEQ.timeData = this_comp.timeData;
end
if ~isempty(this.savePath)
......
......@@ -88,6 +88,7 @@ classdef itaHpTF_MS < itaHpTF
% Measure Right side
MS.inputChannels = chIn(2);
MS.outputChannels = chOut(2);
commandwindow
resultR = MS.run;
resultR.channelNames{1} = strR;
......@@ -108,7 +109,7 @@ classdef itaHpTF_MS < itaHpTF
disp(['Measurement ',num2str(idxM),'/',num2str(this.repeat),' finished.'])
disp('Put headphones off and on again. Press any key to continue.')
pause
pause(2)
pause(1)
else
commandwindow
fprintf('\nMEASUREMENT DONE!\n')
......@@ -118,6 +119,7 @@ classdef itaHpTF_MS < itaHpTF
MS.inputChannels = chIn;
HpTF = itaHpTF_Audio(this);
HpTF.selectMeas = 1:this.repeat;
assignin('base', ['HpTF_' this.nameSubj], HpTF)
end
......
......@@ -40,7 +40,8 @@ ignoreList = {'.svn', ...
'doc', ...
'GuiCallbacks', ...
'external_packages', ...
'ExternalPackages'};
'ExternalPackages', ...
'helpers'};
pathStr = genpath(sArgs.rootpath);
prefixToolbox = fliplr(strtok(fliplr(sArgs.rootpath),filesep)); %get Toolbox folder name
......
......@@ -52,8 +52,15 @@ if abs(dot(v,u,2)) > 1e-5
end
% normalize view/up vectors
v = normr(v);
u = normr(u);
[~,colv]=size(v);
[~,colu]=size(u);
if (colv == 1)
v(~isnan(v(:,1)),:) = v(~isnan(v(:,1)),:) ./ abs(v(~isnan(v(:,1)),:));
u(~isnan(u(:,1)),:) = u(~isnan(u(:,1)),:) ./ abs(u(~isnan(u(:,1)),:));
else
v = sqrt( ones ./ (sum((v(~isnan(v(:,1)),:).*v(~isnan(v(:,1)),:))')) )' * ones(1,colv).*v(~isnan(v(:,1)),:);
u = sqrt( ones ./ (sum((u(~isnan(u(:,1)),:).*u(~isnan(u(:,1)),:))')) )' * ones(1,colu).*u(~isnan(u(:,1)),:);
end
% calculate side vector
s = cross(v, u);
......@@ -65,7 +72,7 @@ qx = qw;
qy = qw;
qz = qw;
for idx = 1:vec_ent;
for idx = 1:vec_ent
% build rotation matrix
R = [s(idx,:); u(idx,:); -v(idx,:)];
......
......@@ -63,8 +63,15 @@ if abs(dot(v,u,2)) > 1e-5
end
% normalize view/up vectors
v(~isnan(v(:,1)),:) = normr(v(~isnan(v(:,1)),:));
u(~isnan(u(:,1)),:) = normr(u(~isnan(u(:,1)),:));
[~,colv]=size(v);
[~,colu]=size(u);
if (colv == 1)
v(~isnan(v(:,1)),:) = v(~isnan(v(:,1)),:) ./ abs(v(~isnan(v(:,1)),:));
u(~isnan(u(:,1)),:) = u(~isnan(u(:,1)),:) ./ abs(u(~isnan(u(:,1)),:));
else
v = sqrt( ones ./ (sum((v(~isnan(v(:,1)),:).*v(~isnan(v(:,1)),:))')) )' * ones(1,colv).*v(~isnan(v(:,1)),:);
u = sqrt( ones ./ (sum((u(~isnan(u(:,1)),:).*u(~isnan(u(:,1)),:))')) )' * ones(1,colu).*u(~isnan(u(:,1)),:);
end
% init.
y = NaN(size(v,1),1);
......
......@@ -114,7 +114,7 @@ classdef itaMSTF < itaMSPlaybackRecord
fieldName = fieldnames(rmfield(this.saveobj,'dateSaved'));
end
for ind = 1:numel(fieldName);
for ind = 1:numel(fieldName)
try
this.(fieldName{ind}) = varargin{1}.(fieldName{ind});
catch errmsg
......@@ -371,11 +371,10 @@ classdef itaMSTF < itaMSPlaybackRecord
%% sweep rate from analytic calculation, only using sweep parameters / PDI
nSamples = ita_nSamples( this.fftDegree );
finalFreqRange = this.finalFreqRange;
% MMT: use nSamples-1 here to be conform with sweep calculation
% based on timeVector and chirp function
finalExcitationLength = (nSamples-1)/this.samplingRate - this.stopMargin;
sweepRate(1) = log2(finalFreqRange(2)/finalFreqRange(1))/finalExcitationLength;
sweepRate(1) = log2(this.finalFreqRange(2)/this.finalFreqRange(1))/finalExcitationLength;
%% sweep rate of analysis of excitation signal
sweepRate(2) = ita_sweep_rate(this.raw_excitation,[2000 this.samplingRate/3]);
......@@ -563,7 +562,7 @@ classdef itaMSTF < itaMSPlaybackRecord
if this.minimumphasedeconvolution
% get minimumphase part of deconvolution, neglect
% all-pass component
[this.mCompensation, allpass_component] = ita_invert_spk_regularization(ita_extend_dat(this.raw_excitation,this.final_excitation.nSamples*factor),[min(this.freqRange(:)) max(this.freqRange(:))],'filter',this.filter);
[this.mCompensation, allpass_component] = ita_invert_spk_regularization(ita_extend_dat(this.raw_excitation,this.final_excitation.nSamples*factor),[min(this.freqRange(:)) max(this.freqRange(:))],'filter',this.filter); %#ok<ASGLU>
else
this.mCompensation = ita_invert_spk_regularization(ita_extend_dat(this.raw_excitation,this.final_excitation.nSamples*factor),[min(this.freqRange(:)) max(this.freqRange(:))],'filter',this.filter);
end
......@@ -619,7 +618,7 @@ classdef itaMSTF < itaMSPlaybackRecord
token = this.(list{idx});
if isempty(token) || isa(token,'itaSuper')
continue;
end;
end
if ischar(token)
token = ['''' token ''''];
......@@ -630,7 +629,7 @@ classdef itaMSTF < itaMSPlaybackRecord
end
else
error([upper(mfilename) '.commandline: What kind of field value is this?']);
end;
end
str = [str '''' list{idx} '''' ',' token ];
if idx < numel(list)
......@@ -643,7 +642,7 @@ classdef itaMSTF < itaMSPlaybackRecord
%% Hidden methods
methods(Hidden = true)
function display(this)
function display(this) %#ok<DISPLAY>
this.excitation; %pre-init
% Begin Display Start Line
......
......@@ -109,7 +109,7 @@
\begin{tabular}{|p{0.43\textwidth}p{0.51\textwidth}|}\hline
\multicolumn{2}{|p{0.99\textwidth}|}{
\underline{Beschreibung der Prfeinrichtung:} \newline
Impedanzmessrohr mit 2 Zoll Bohrung aus Aluminium. Probenhalter mit verstellbarem Rohrabschluss durch massiven, abgedichteten Aluminiumkolben. Messrohr mit vier Mikrofonbohrungen (Distanzen zur ersten Position: 17~mm, 110~mm, 510~mm). Sondenmikrofon mit Abnahme des Schallfelds im Rohrmittelpunkt. Auswertbarer Frequenzbereich ca.~100 Hz bis 8 kHz durch Ausblendung der ersten zwei Rohrmoden. Breitbandige Anregung mittels Sinus-Sweeps. Auswertung nach ISO 10534-2 mit Hilfe einer im ITA entwickelten FFT-Messtechnik.}\\
Impedanzmessrohr mit 2 Zoll Bohrung aus Aluminium. Probenhalter mit verstellbarem Rohrabschluss durch massiven, abgedichteten Aluminiumkolben. Messrohr mit vier Mikrofonbohrungen (Distanzen zur ersten Position: 17~mm, 110~mm, 510~mm). Sondenmikrofon zur Abnahme des Schallfelds im Rohrmittelpunkt. Auswertbarer Frequenzbereich ca.~100 Hz bis 8 kHz durch Ausblendung der ersten zwei Rohrmoden. Breitbandige Anregung mittels Sinus-Sweeps. Auswertung nach ISO 10534-2 mit Hilfe einer im ITA entwickelten FFT-Messtechnik.}\\
&\\
Prfdatum: & \datumDerMessung \\
Prfer: & \nameDesPruefers\\
......
This diff is collapsed.
function varargout = ita_NI_daq_run(varargin)
% ITA_NI_DAQ_RUN play and record sound with NI card and DAQ toolbox (adapted from ita_portaudio_run)
% see ita_portaudio_run for options and help
% Autor: Markus Mueller-Trapet -- Email: markus.mueller-trapet@nrc.ca
% Created: 13-Apr-2017
%% ITA Toolbox preferences for verbose level
verboseMode = ita_preferences('verboseMode');
%% Input checks
if isa(varargin{1},'itaAudio')
% if a signal is the first input, then playback that signal
sArgs.pos1_data = 'itaAudioTime';
playback = true;
else
% otherwise just record for the given number of samples
sArgs.pos1_data = 'numeric';
playback = false;
end
% second argument has to be the DAQ NI session
sArgs.pos2_niSession = 'anything';
% only do recording if requested
if nargout > 0
record = true;
else
record = false;
end
%% Init Settings
sArgs.normalizeinput = false;
sArgs.normalizeoutput = false;
sArgs.inputchannels = [];
sArgs.outputchannels = [];
sArgs.recsamples = -1;
sArgs.repeats = 1;
sArgs.samplingRate = -1; % will always be taken from NI session
% cancel button and monitor not supported currently, but kept for compatibility
sArgs.cancelbutton = ita_preferences('portAudioMonitor'); % -1:automatic; 0:off; 1:on
sArgs.latencysamples = 0;
sArgs.singleprecision = false;
[data, niSession, sArgs] = ita_parse_arguments(sArgs,varargin);
if ~playback && sArgs.recsamples == -1
sArgs.recsamples = data;
end
sArgs.samplingRate = round(niSession.Rate); % NI rate is not exact
in_channel_vec = sArgs.inputchannels;
out_channel_vec = sArgs.outputchannels;
normalize_input = sArgs.normalizeinput;
normalize_output = sArgs.normalizeoutput;
if ~playback && ~record
error('ITA_NI_DAQ_RUN:What do you want? Play or Record, or both? You need to specify an input and/or an output!')
end
if playback
% Extract channels to play
% are there enough channels to play
if data.nChannels == 1 && (length(out_channel_vec) > 1) %playback the same on alle channels activated
ita_verbose_info('Oh Lord. I will playback the same on all channels.', 2)
nChannelsToPlay = length(out_channel_vec);
data = data.ch(ones(1,nChannelsToPlay)); %duplicated data to all channels
elseif data.nChannels < length(out_channel_vec) %too many output channels for this input data
ita_verbose_info('Not enough channels in data to play.',0)
out_channel_vec = out_channel_vec(1:data.nChannels);
elseif data.nChannels > length(out_channel_vec)
ita_verbose_info('Too many channels in data file, I will only play the first ones',1);
data = ita_split(data,1:length(out_channel_vec));
end
% Show channel data if requested
if verboseMode==2
ita_metainfo_show_channelnames(data);
end
% Check levels - Normalizing
peak_value = max(max(abs(data.timeData)));
if (peak_value > 1) || (normalize_output)
ita_verbose_info('Oh Lord! Levels too high for playback. Normalizing...',0)
data = ita_normalize_dat(data);
end
end
%% Extend excitation to compensate soundcard latency
if playback && record && ~isempty(sArgs.latencysamples) && (sArgs.latencysamples > 0)
latencysamples = sArgs.latencysamples;
data = ita_extend_dat(data,data.nSamples+latencysamples,'forcesamples');
end
% record as many samples as are in the playback signal
if playback
sArgs.recsamples = data.nSamples;
end
% Full (double) precision
recordDatadat = zeros(sArgs.recsamples,numel(in_channel_vec),sArgs.repeats);
if sArgs.singleprecision % only single precision
recordDatadat = single(recordDatadat);
end
% run measurement, possibly repeated
for idrep = 1:sArgs.repeats
if playback && record
niSession.queueOutputData(double(data.time));
ita_verbose_info('start playback and record',1)
elseif record
niSession.queueOutputData(zeros(sArgs.recsamples,1));
ita_verbose_info('start record',1)
elseif playback
niSession.queueOutputData(double(data.time));
ita_verbose_info('start playback',1)
else
error('ITA_NI_DAQ_run:No input and no output, what should I do?')
end
pause(0.01)
% do the measurement
if ~sArgs.singleprecision % Full (double) precision
recordDatadat(:,:,idrep) = niSession.startForeground();
else
recordDatadat(:,:,idrep) = single(niSession.startForeground());
end
end % loop for repeats
ita_verbose_info('playback/record finished ',1);
recordData = itaAudio();
recordData.dataType = class(recordDatadat);
recordData.dataTypeOutput = class(recordDatadat);
% Check if we need to average multiple measurements:
if size(recordDatadat,3) > 1
% average:
recordData.timeData = mean(recordDatadat,3);
else
% no average: (This saves memory!)
recordData.timeData = recordDatadat;
end
recordData.samplingRate = sArgs.samplingRate;
for idx = 1:numel(in_channel_vec)
recordData.channelNames{idx} = ['Ch ' int2str(in_channel_vec(idx))];
end
%% Remove Latency
if playback && record && ~isempty(sArgs.latencysamples) && (sArgs.latencysamples > 0)
recordData = ita_extract_dat(recordData,recordData.nSamples-latencysamples,'firstsample',latencysamples+1);
end
%% Check for clipping and other errors
clipping = false;
if record
if any(any(abs(recordData.timeData)>=10)) % Check for clipping (NI card actually handles up to 10Vpk)
ita_verbose_info('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!',0);
ita_verbose_info('!ITA_NI_DAQ_RUN:Careful, Clipping!',0);
ita_verbose_info('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!',0);
clipping = true;
end
% This check for singularities needs a lot of memory! TODO: find a
% better solution!:
if any(isnan(recordData.timeData(:))) || any(isinf(recordData.timeData(:))) %Check for singularities
ita_verbose_info('There are singularities in the audio signal! You''d better check your settings!',0)
clipping = true;
end
if any(all(recordData.timeData == 0,1)) && record
ita_verbose_info('There are empty channels in the audio signal! You''d better check your settings!',0)
end
% maximum for each channel
maxData = max(abs(recordData.timeData),[],1);
[channelMax, indexMax] = max(maxData);
% jri: to detect non working microphones etc, the minimum of the
% maximums on the channels is also outputted
if length(in_channel_vec) > 1
[channelMin, indexMin] = min(maxData);
ita_verbose_info(['Minimum digital level: ' int2str(20*log10(channelMin)) ' dBFS on channel: ' int2str(in_channel_vec(indexMin))],0);
end
ita_verbose_info(['Maximum digital level: ' int2str(20*log10(channelMax)) ' dBFS on channel: ' int2str(in_channel_vec(indexMax))],0);
end
%% Add history line
infosforhistory = struct('PlayDevice','NI','Play_Channels',out_channel_vec,'RecDevice','NI','Rec_Channels',in_channel_vec,'Sampling_Rate',niSession.Rate,'Normalize_Input',normalize_input,'Normalize_Output',0,'Rec_Samples',sArgs.recsamples,'Block',1,'Repeats',sArgs.repeats);
recordData = ita_metainfo_add_historyline(recordData,'ita_NI_daq_run',[{data}; ita_struct2arguments(infosforhistory)],'withsubs');
if clipping
recordData = ita_metainfo_add_historyline(recordData,'!!!ITA_NI_DAQ_RUN:Careful, clipping or something else went wrong!!!');
recordData = ita_errorlog_add(recordData,'!!!ITA_NI_DAQ_RUN:Careful, clipping or something else went wrong!!!');
end
%% Find output parameters
if nargout ~= 0
if normalize_input
ita_normalize_dat(recordData)
end
varargout{1} = recordData;
end
end % function
\ No newline at end of file
function varargout = ita_channelselect_gui_ni( varargin )
% Show gui to select channels for input and output (NI hardware)
%
% Syntax: [in_ch out_ch] = ita_channelselect_gui_ni()
% [in_ch out_ch] = ita_channelselect_gui_ni(in_ch_preselct, out_ch_preselect)
%
% <ITA-Toolbox>
% This file is part of the ITA-Toolbox. Some rights reserved.
% You can find the license for this m-file in the license.txt file in the ITA-Toolbox folder.
% </ITA-Toolbox>
% Author: Markus Mueller-Trapet -- Email: markus.mueller-trapet@nrc.ca
% Created: 10-May-2017