Commit 3d635eb7 authored by Dipl.-Ing. Jonas Stienen's avatar Dipl.-Ing. Jonas Stienen
Browse files

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

parents f6a06115 ca88b2c5
...@@ -662,6 +662,10 @@ classdef itaHRTF < itaAudio ...@@ -662,6 +662,10 @@ classdef itaHRTF < itaAudio
%HRTFout = this.direction(idxCoord); %HRTFout = this.direction(idxCoord);
end end
function this = buildsearchdatabase(this)
this.dirCoord = this.dirCoord.build_search_database;
end
function obj = direction(this, idxCoord) function obj = direction(this, idxCoord)
idxDir = zeros(numel(idxCoord)*2,1); idxDir = zeros(numel(idxCoord)*2,1);
idxDir(1:2:numel(idxCoord)*2,:) = 2*idxCoord-1; idxDir(1:2:numel(idxCoord)*2,:) = 2*idxCoord-1;
...@@ -706,11 +710,17 @@ classdef itaHRTF < itaAudio ...@@ -706,11 +710,17 @@ classdef itaHRTF < itaAudio
if ~exactSearch if ~exactSearch
phiU = rad2deg(this.phi_Unique); phiU = rad2deg(this.phi_Unique);
thetaU = rad2deg(this.theta_Unique); thetaU = rad2deg(this.theta_Unique);
switch dirID
case {'phi_deg', 'p'}
slice = this.findnearestHRTF(thetaU,dir_deg);
case {'theta_deg', 't'}
slice = this.findnearestHRTF(dir_deg,phiU);
end
else else
earCoords = this.getEar('L').channelCoordinates; earCoords = this.getEar('L').channelCoordinates;
switch dirID switch dirID
case {'phi_deg', 'p'} case {'phi_deg', 'p'}
phiValues = unique(earCoords.phi_deg); phiValues = uniquetol(earCoords.phi_deg);
[~,index] = min(abs(phiValues - dir_deg)); [~,index] = min(abs(phiValues - dir_deg));
exactPhiValue = phiValues(index); exactPhiValue = phiValues(index);
tmp = earCoords.n(earCoords.phi_deg == exactPhiValue); tmp = earCoords.n(earCoords.phi_deg == exactPhiValue);
...@@ -718,7 +728,7 @@ classdef itaHRTF < itaAudio ...@@ -718,7 +728,7 @@ classdef itaHRTF < itaAudio
slice = this.findnearestHRTF(thetaU,dir_deg); slice = this.findnearestHRTF(thetaU,dir_deg);
case {'theta_deg', 't'} case {'theta_deg', 't'}
thetaValues = unique(earCoords.theta_deg); thetaValues = uniquetol(earCoords.theta_deg);
[~,index] = min(abs(thetaValues - dir_deg)); [~,index] = min(abs(thetaValues - dir_deg));
exactThetaValue = thetaValues(index); exactThetaValue = thetaValues(index);
tmp = earCoords.n(earCoords.theta_deg == exactThetaValue); tmp = earCoords.n(earCoords.theta_deg == exactThetaValue);
...@@ -727,12 +737,7 @@ classdef itaHRTF < itaAudio ...@@ -727,12 +737,7 @@ classdef itaHRTF < itaAudio
slice = this.findnearestHRTF(dir_deg,phiU); slice = this.findnearestHRTF(dir_deg,phiU);
end end
end end
switch dirID
case {'phi_deg', 'p'}
slice = this.findnearestHRTF(thetaU,dir_deg);
case {'theta_deg', 't'}
slice = this.findnearestHRTF(dir_deg,phiU);
end
end end
function slice = ss(this,dirID,dir_deg) function slice = ss(this,dirID,dir_deg)
...@@ -911,10 +916,12 @@ classdef itaHRTF < itaAudio ...@@ -911,10 +916,12 @@ classdef itaHRTF < itaAudio
ITD = phasenDiff./(2*pi*repmat(thisC.freqVector,1,size(phase1,2))); ITD = phasenDiff./(2*pi*repmat(thisC.freqVector,1,size(phase1,2)));
else % averaged else % averaged
phase = unwrap(angle(thisC.freqData)); usedBins = thisC.freq2index(sArgs.filter(1)):thisC.freq2index(sArgs.filter(2));
t0_freq = bsxfun(@rdivide, phase,2*pi*thisC.freqVector); phase = unwrap(angle(thisC.freqData(2:end,:)));
freqVector = thisC.freqVector;
t0_freq = bsxfun(@rdivide, phase,2*pi*freqVector(2:end));
t0_freq = t0_freq(~isnan(t0_freq(:,1)),:); t0_freq = t0_freq(~isnan(t0_freq(:,1)),:);
t0_mean = mean(t0_freq(unique(thisC.freq2index(sArgs.filter(1)):thisC.freq2index(sArgs.filter(2))),:)); %mean is smoother than max; lower freq smooths also the result t0_mean = mean(t0_freq(usedBins,:)); %mean is smoother than max; lower freq smooths also the result
ITD = t0_mean(thisC.EarSide == 'L') - t0_mean(thisC.EarSide == 'R'); ITD = t0_mean(thisC.EarSide == 'L') - t0_mean(thisC.EarSide == 'R');
end end
case 'xcorr' case 'xcorr'
...@@ -1312,10 +1319,10 @@ classdef itaHRTF < itaAudio ...@@ -1312,10 +1319,10 @@ classdef itaHRTF < itaAudio
ita_verbose_info(' More than one elevation in this object!', 0); ita_verbose_info(' More than one elevation in this object!', 0);
if strcmp(sArgs.plane,'horizontal') if strcmp(sArgs.plane,'horizontal')
thetaC_deg = 90; thetaC_deg = 90;
thisC = this.sphericalSlice('theta_deg', thetaC_deg); thisC = this.sphericalSlice('theta_deg', thetaC_deg,1);
elseif strcmp(sArgs.plane,'median') elseif strcmp(sArgs.plane,'median')
phiC_deg = 0; phiC_deg = 0;
thisC = this.sphericalSlice('phi_deg', phiC_deg); thisC = this.sphericalSlice('phi_deg', phiC_deg,1);
end end
else thisC = this; else thisC = this;
end end
......
This diff is collapsed.
Copyright (c) 2014, Oliver J. Woodford, Yair M. Altman
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Copyright (c) 2017, Yair Altman
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
...@@ -95,7 +95,7 @@ lowerTolVal = sArgs.distortionLimit * (1-sArgs.tolerance); ...@@ -95,7 +95,7 @@ lowerTolVal = sArgs.distortionLimit * (1-sArgs.tolerance);
%% go through the excitation frequencies, process measurement %% go through the excitation frequencies, process measurement
ita_verbose_info('Measurement process',1); ita_verbose_info('Measurement process',1);
wb = itaWaitbar([numel(excitationFreq),numel(sArgs.distortionLimit)],'maxSPL',{'Frequencies','Limits'});
% frequency band loop with freqIdx % frequency band loop with freqIdx
for freqIdx = 1:numel(excitationFreq) for freqIdx = 1:numel(excitationFreq)
...@@ -108,7 +108,7 @@ for freqIdx = 1:numel(excitationFreq) ...@@ -108,7 +108,7 @@ for freqIdx = 1:numel(excitationFreq)
% distortion limit loop % distortion limit loop
for distIdx = 1:numel(sArgs.distortionLimit) for distIdx = 1:numel(sArgs.distortionLimit)
wb.inc
% Amplification and measurement % Amplification and measurement
while outputVoltage >= (outputVoltageRange(1)/10) && outputVoltage <= outputVoltageRange(2) while outputVoltage >= (outputVoltageRange(1)/10) && outputVoltage <= outputVoltageRange(2)
...@@ -211,11 +211,10 @@ for freqIdx = 1:numel(excitationFreq) ...@@ -211,11 +211,10 @@ for freqIdx = 1:numel(excitationFreq)
if breakFlag if breakFlag
breakFlag = false; breakFlag = false;
break; break;
end end
end end
end end
wb.close;
%% Post-processing and Results %% Post-processing and Results
......
...@@ -88,8 +88,8 @@ classdef itaMSTFni < itaMSTF ...@@ -88,8 +88,8 @@ classdef itaMSTFni < itaMSTF
% Define listeners to automatically call the init function of % Define listeners to automatically call the init function of
% this class in case of a change in the below specified % this class in case of a change in the below specified
% properties. % properties.
addlistener(this,'inputChannels','PostSet',@this.init); addlistener(this,'inputChannels','PostSet',@this.init_ni);
addlistener(this,'outputChannels','PostSet',@this.init); addlistener(this,'outputChannels','PostSet',@this.init_ni);
end end
function this = edit(this) function this = edit(this)
...@@ -100,11 +100,10 @@ classdef itaMSTFni < itaMSTF ...@@ -100,11 +100,10 @@ classdef itaMSTFni < itaMSTF
this = ita_mstfni_gui(this); this = ita_mstfni_gui(this);
end end
function this = init(this,varargin) function this = init_ni(this,varargin)
% init - Initialize the itaMSTFni class object. % init - Initialize the itaMSTFni class object.
init@itaMSTF(this);
% if this is an object loaded from disk (niSession is empty), % if this is an object loaded from disk (niSession is empty),
% we do not need to initialize the card % we do not need to re-initialize the card
if ~isempty(this.niSession) if ~isempty(this.niSession)
this.niSession = init_NI_card(this); this.niSession = init_NI_card(this);
end end
...@@ -281,9 +280,6 @@ classdef itaMSTFni < itaMSTF ...@@ -281,9 +280,6 @@ classdef itaMSTFni < itaMSTF
niSession.Channels(end).Name = inputChannels.name{iChannel}; niSession.Channels(end).Name = inputChannels.name{iChannel};
% set to AC coupling to get rid of large DC offset % set to AC coupling to get rid of large DC offset
niSession.Channels(end).Coupling = 'AC'; niSession.Channels(end).Coupling = 'AC';
% if any(strcmpi(Channels.type{iDevice,iChannel},{'Accelerometer' 'Microphone'}))
% niSession.Channels(end).Sensitivity = Channels.sensitivity(iDevice,iChannel);
% end
end end
end end
...@@ -307,6 +303,46 @@ classdef itaMSTFni < itaMSTF ...@@ -307,6 +303,46 @@ classdef itaMSTFni < itaMSTF
end % function end % function
function this = set_IEPE_channels(this,channelIds)
if isempty(this.niSession)
this.niSession = this.init_NI_card();
end
% first get NI info
[inputChannels,~,niDevices,~] = ita_get_ni_deviceinfo();
% INPUT
% set channel data from MS
channelIds = intersect(channelIds,this.inputChannels);
if isempty(channelIds)
error('Nothing to do, maybe your channels are not active?');
end
inputChannels.mapping = inputChannels.mapping(channelIds);
inputChannels.name = inputChannels.name(channelIds);
inputChannels.type = inputChannels.type(channelIds);
inputChannels.sensitivity = inputChannels.sensitivity(channelIds);
inputChannels.isActive = inputChannels.isActive(channelIds);
% Add analog input channels with IEPE supply
for iChannel = 1:numel(channelIds)
devIdx = [];
for iCh = 1:numel(this.niSession.Channels)
if strcmpi(inputChannels.name{iChannel},this.niSession.Channels(iCh).Name)
devIdx = iCh;
end
end
if ~isempty(devIdx)
this.niSession.removeChannel(devIdx);
else
error('Could not find your channel');
end
% then add again
iDevice = inputChannels.mapping{iChannel}(1);
iDeviceChannel = inputChannels.mapping{iChannel}(2);
this.niSession.addAnalogInputChannel(get(niDevices(iDevice),'ID'),iDeviceChannel-1,'IEPE');
this.niSession.Channels(end).Name = inputChannels.name{iChannel};
end
end % function
function sObj = saveobj(this) function sObj = saveobj(this)
% saveobj - Saves the important properties of the current % saveobj - Saves the important properties of the current
% measurement setup to a struct. % measurement setup to a struct.
......
...@@ -92,7 +92,7 @@ if playback ...@@ -92,7 +92,7 @@ if playback
peak_value = max(max(abs(data.timeData))); peak_value = max(max(abs(data.timeData)));
if (peak_value > outputClipping) || (normalize_output) if (peak_value > outputClipping) || (normalize_output)
ita_verbose_info('Oh Lord! Levels too high for playback. Normalizing...',0) ita_verbose_info('Oh Lord! Levels too high for playback. Normalizing...',0)
data = ita_normalize_dat(data); data = data/peak_value*outputClipping;
end end
end end
......
...@@ -414,6 +414,7 @@ function [] = daffv17_write( varargin ) ...@@ -414,6 +414,7 @@ function [] = daffv17_write( varargin )
% note: use round here to avoid errors if alphapoints are not exactly % note: use round here to avoid errors if alphapoints are not exactly
% integers but within epsilon % integers but within epsilon
x = cell( round( args.alphapoints ), round( args.betapoints ), args.channels ); x = cell( round( args.alphapoints ), round( args.betapoints ), args.channels );
args.userdata = args.userdata.buildsearchdatabase;
for b=1:args.betapoints for b=1:args.betapoints
beta = betastart + (b-1)*args.betares; beta = betastart + (b-1)*args.betares;
...@@ -422,13 +423,11 @@ function [] = daffv17_write( varargin ) ...@@ -422,13 +423,11 @@ function [] = daffv17_write( varargin )
points = 1; points = 1;
else else
points = args.alphapoints; points = args.alphapoints;
end end
for a=1:points for a=1:points
alpha = alphastart + (a-1)*args.alphares; alpha = alphastart + (a-1)*args.alphares;
% --= Impulse responses =-- % --= Impulse responses =--
if strcmp( args.content, 'IR' ) if strcmp( args.content, 'IR' )
% Get the data % Get the data
[ data, samplerate, metadata ] = args.datafunc( alpha, beta, args.userdata ); [ data, samplerate, metadata ] = args.datafunc( alpha, beta, args.userdata );
......
...@@ -508,7 +508,7 @@ classdef itaSuper < itaMeta ...@@ -508,7 +508,7 @@ classdef itaSuper < itaMeta
function res = get_diag(this) function res = get_diag(this)
% use eye as mask for diagonal % use eye as mask for diagonal
res = this(eye(size(this,1))); res = this(logical(eye(size(this,1))));
end end
function this = diag(this,diagonalshift,blocksize) function this = diag(this,diagonalshift,blocksize)
......
...@@ -24,39 +24,35 @@ function varargout = ita_multiple_time_windows(varargin) ...@@ -24,39 +24,35 @@ function varargout = ita_multiple_time_windows(varargin)
sArgs = struct('pos1_a','itaAudioTime','blocksize',1024,'window',@hann,'overlap',0.5); sArgs = struct('pos1_a','itaAudioTime','blocksize',1024,'window',@hann,'overlap',0.5);
[a,sArgs] = ita_parse_arguments(sArgs,varargin); [a,sArgs] = ita_parse_arguments(sArgs,varargin);
b = sArgs.blocksize;
nWindow = b; nWindow = sArgs.blocksize;
if sArgs.overlap < 1 if sArgs.overlap < 1
nOverlap = round(nWindow*sArgs.overlap); nOverlap = round(nWindow*sArgs.overlap);
else else
nOverlap = round(sArgs.overlap); nOverlap = round(sArgs.overlap);
end end
nSegments = ceil(a.nSamples / nWindow * 2 + 1); % half a window length at beginning and end
nNewLength = (nSegments -1) * nWindow / 2; ext_zeros = zeros(nWindow/2,a.nChannels);
data = [ext_zeros; a.time; ext_zeros];
nSegments = ceil((size(data,1) - nWindow) / (nWindow - nOverlap)) + 1;
nNewLength = (nSegments - 1) * (nWindow - nOverlap) + nWindow;
if nNewLength > a.nSamples if nNewLength > a.nSamples
a = ita_extend_dat(a,nNewLength,'forcesamples'); a = ita_extend_dat(a,nNewLength,'forcesamples');
end end
%% generate window %% generate window
win_vec = window(sArgs.window,nWindow+1).'; win_vec = window(sArgs.window,nWindow+1);
win_vec(end) = []; win_vec(end) = [];
ext_zeros = zeros(a.nChannels,nWindow/2);
data = [ext_zeros a.dat(:,:) ext_zeros];
resultDummy = a; resultDummy = a;
resultDummy.data = zeros(1,a.nChannels); resultDummy.data = zeros(1,a.nChannels);
result = repmat(resultDummy,nSegments,1); result = repmat(resultDummy,nSegments,1);
for idx = 1:nSegments for idx = 1:nSegments
iLow = (idx-1)*(nWindow-nOverlap)+1; sliceIds = (idx-1)*(nWindow-nOverlap) + (1:nWindow);
iHigh = iLow+nWindow-1; result(idx).time = bsxfun(@times,data(sliceIds,:),win_vec);
slice = bsxfun(@times,data(:,iLow:iHigh),win_vec);
result(idx).time = slice.';
end end
%% %%
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment