Commit 37b53cbc authored by Lukas Aspöck's avatar Lukas Aspöck
Browse files

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

parents 466f9b3f fdde5352
......@@ -40,7 +40,7 @@ dataUnit = sofaObj.(sprintf('%s_Units',coordinateType));
coordinates = itaCoordinates(size(data,1));
switch dataType
case 'cartesian'
if strcmpi(dataUnit,'meter')
if strcmpi(dataUnit,'meter')||strcmpi(dataUnit,'metre')
coordinates.x = data(:,1);
coordinates.y = data(:,2);
coordinates.z = data(:,3);
......
# ITA-Toolbox test
# ITA-Toolbox
Welcome to the ITA-Toolbox
* Open source project developed by the [Institute of Technical Acoustics](http://www.akustik.rwth-aachen.de/), [RWTH Aachen University](http://www.rwth-aachen.de/).
......
function writeDAFFFile( this, filePath, metadata_user )
function writeDAFFFile( this, file_path, metadata_user )
% Exports itaHRTF to a DAFF file
%
% Input: filePath / fileName (string) [optional]
% Input: file_path (string) [optional]
% user metadata (struct created with daff_add_metadata) [optional]
%
% Required: OpenDAFF matlab scripts, http://www.opendaff.org
......@@ -15,9 +15,9 @@ if nargin >= 3
end
hrtf_variable_name = inputname( 1 );
fileName = [ hrtf_variable_name '_' int2str( this.nSamples ) 'samples_' int2str( this.resAzimuth ) 'x' int2str(this.resElevation) '.daff'];
file_name = [ hrtf_variable_name '_' int2str( this.nSamples ) 'samples_' int2str( this.resAzimuth ) 'x' int2str( this.resElevation ) '.daff'];
if nargin >= 2
fileName = filePath;
file_name = file_path;
end
if nargin == 0
......@@ -32,12 +32,11 @@ if strcmp( this.domain, 'freq' )
ct_indicator = 'dft';
end
file_path = '';
file_path_base = strsplit( fileName, '.' );
if ~strcmp( file_path_base(end), 'daff' )
file_path = strjoin( [ file_path_base(:) ct_indicator 'daff' ], '.' );
[ file_path, file_base_name, file_suffix ] = fileparts( file_name );
if ~strcmp( file_suffix, '.daff' )
file_path = fullfile( file_path, strjoin( {file_base_name file_suffix 'v17' ct_indicator 'daff' }, '.' ) );
else
file_path = strjoin( [ file_path_base(1:end-1) ct_indicator 'daff' ], '.' );
file_path = fullfile( file_path, strjoin( {file_base_name 'v17' ct_indicator 'daff'}, '.' ) );
end
......@@ -47,8 +46,8 @@ 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 );
phi_start_deg = rad2deg( min( this.channelCoordinates.phi ) );
phi_end_deg = rad2deg( max( this.channelCoordinates.phi ) );
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 );
assert( phi_num_elements ~= 0 );
......
function varargout = ita_HRTFarc_postprocessing(varargin)
%% parse arguments
sArgs = struct('dataPath',[],'savePath',[],'saveName',[],'path_ref',...
[],'ref_name',[],'tWin',[],'samples',[],'flute',[],'phiAdd',0,'eimar',true,'refIsCropped',0);
sArgs = ita_parse_arguments(sArgs,varargin);
dataPath = sArgs.dataPath; % Pfad des Ordners mit den HRTF Rohdaten
path_ref = sArgs.path_ref; % Pfad der Referenzmessung linkes Mikro
savePath = sArgs.savePath; % Pfad angeben, falls gefensterte HRTF gespeichert werden soll
saveName = sArgs.saveName; % Dateiname (ohne .ita Endung)
if isempty(sArgs.samples),
if numel(sArgs.tWin) ==1, t2 = sArgs.tWin(1); t1 = t2/1.25;
else t1 = sArgs.tWin(1); t2 = sArgs.tWin(2);
end
else
SR = 44100;
if numel(sArgs.samples) ==1, t2 = sArgs.samples(1)/SR; t1 = t2/1.25;
else t1 = sArgs.samples(1); t2 = sArgs.samples(2);
end
end
%% coord & userData
allFolders = dir(fullfile(dataPath,'*.ita'));
numAzAngle = size(allFolders,1);
elAngle_arc = sArgs.flute.theta;
coordHRTF = itaCoordinates;
coordHRTF.sph = zeros(numel(elAngle_arc)*numAzAngle ,3);
coordHRTF.r = ones(numel(elAngle_arc)*numAzAngle,1)*1.2;
%% Post processing Window
HRTF_TMP_L = itaAudio(numAzAngle,1);
HRTF_TMP_R = itaAudio(numAzAngle,1);
channelCounter = 1;
currentPath = dataPath;
%% Main processing Ref and Window
wb = itaWaitbar(numAzAngle, 'calculate HRTF', {'azimuth'});
% reference
% first determine how many channels the measurement has
currentDataEnding = num2str(1);
currentData = ita_merge(ita_read([currentPath filesep currentDataEnding '.ita']));
numChannels = currentData.nChannels;
%read the reference
currentRefTmp = ita_read([path_ref filesep sArgs.ref_name '.ita']);
currentRef = merge(currentRefTmp(1:1:length(currentRefTmp)));
if currentRef.nChannels == 2
error('Reference might not be cropped yet.');
end
if currentRef.nChannels == numChannels
refLeftChan0 = currentRef.ch(1:2:currentRef.nChannels); % a channel cloe to theta = 90�
refRightChan0 = currentRef.ch(2:2:currentRef.nChannels);
else
refLeftChan0 = currentRef;
refRightChan0 = currentRef;
end
refLeftChan0c = ita_minimumphase(ita_time_window(refLeftChan0,[t1 t2],'time','crop'));
refRightChan0c = ita_minimumphase(ita_time_window(refRightChan0 ,[t1 t2],'time','crop'));
%.........................................................................
% Smooting
%.........................................................................
refLeftChan0c = ita_smooth_notches(refLeftChan0c,'bandwidth',1/2,...
'threshold', 3);
refRightChan0c = ita_smooth_notches(refLeftChan0c,'bandwidth',1/2,...
'threshold', 3);
for iAz = 1:numAzAngle
%currentAz_front = mod(360-azAngle(iAz),360); % vordere H�lfte des Lautsprecherbogens: Azimutwinkel = azAngle
%.........................................................................
% read HRTF raw data
%.........................................................................
currentDataEnding = num2str(iAz);
try
currentData = ita_merge(ita_read([currentPath filesep currentDataEnding '.ita']));
if sArgs.eimar
phi = mod(2*pi-currentData.channelCoordinates.phi+deg2rad(sArgs.phiAdd) ,2*pi);
else phi = mod(currentData.channelCoordinates.phi+deg2rad(sArgs.phiAdd) ,2*pi);
end
catch
disp('help me')
end
%.........................................................................
% Divide itaAudio in 2 parts for left and right ear
%.........................................................................
currentDataS = currentData;
currentDataSave(iAz,1) = currentData.ch(1:2:currentDataS.dimensions);
currentDataSL0 = ita_time_window(currentDataS.ch(1:2:currentDataS.dimensions),[t1 t2],'time','crop');
currentDataSR0 = ita_time_window(currentDataS.ch(2:2:currentDataS.dimensions),[t1 t2],'time','crop');
% refRightChan0S = refLeftChan0S;
%
% if mod(refLeftChan0S.nSamples,2) == 1 % ungerade Anzahl an Samples!
% refLeftChan0S.trackLength = refLeftChan0c.trackLength-1/refLeftChan0c.samplingRate;
% refRightChan0S.trackLength = refLeftChan0c.trackLength-1/refLeftChan0c.samplingRate;
% currentDataSL0.trackLength = refLeftChan0c.trackLength-1/refLeftChan0c.samplingRate;
% currentDataSR0.trackLength = refLeftChan0c.trackLength-1/refLeftChan0c.samplingRate;
% end
%.........................................................................
% Calculate HRTF
%.........................................................................
HRTF_TMP_L(iAz,1) = ita_divide_spk(currentDataSL0,refLeftChan0c ,'regularization',[100,20000]);
HRTF_TMP_R(iAz,1) = ita_divide_spk(currentDataSR0,refRightChan0c,'regularization',[100,20000]);
%.........................................................................
% Coordinates
%.........................................................................
coordHRTF.theta(channelCounter:channelCounter+ numel(elAngle_arc)-1) = elAngle_arc;
coordHRTF.phi(channelCounter:channelCounter+ numel(elAngle_arc)-1) = phi(1:2:end);
channelCounter = channelCounter+numel(elAngle_arc);
wb.inc
end
wb.close
%% Merge HRTF
HRTF_R = HRTF_TMP_R(1:iAz).merge;
HRTF_R.channelCoordinates = coordHRTF;
HRTF_L = HRTF_TMP_L(1:iAz).merge;
HRTF_L.channelCoordinates = coordHRTF;
HRTF_sWin = ita_merge(HRTF_L,HRTF_R);
if ~isempty(sArgs.samples),HRTF_sWin.nSamples = round(t2*SR);end
%%
[~, deltaT] = ita_time_shift( HRTF_sWin,'20dB'); % Shift der IR nach vorn
deltaTmin = min(deltaT);
deltaT2 = 1e-3;
HRTF_shift = ita_time_shift(HRTF_sWin , deltaTmin+deltaT2); % shifte Signale an den Anfang
HRTF = ita_time_window(HRTF_shift, [t1 t2],'time','crop'); % Window
% HRTF.ch(1:32).ptd
%% save (is it working?)
if ~isempty(saveName) && ~isempty(savePath)
ita_write(HRTF,fullfile(savePath, [saveName '.ita']));
end
%% out
if nargout <4
varargout{1} = HRTF;
if nargout >1
varargout{2} = coordHRTFout;
end
end
end
\ No newline at end of file
......@@ -60,6 +60,20 @@ classdef itaHpTF_Audio < itaHpTF
this = varargin;
elseif isa(varargin{1},'itaHpTF_MS')
this.init = varargin{1};
elseif nargin ==1 && isstruct(varargin{1}) % only for loading
obj = varargin{1};
this.data = obj.data;
this.signalType = 'energy';
% additional itaHRTF data
objFNsaved = this.propertiesSaved;
objFNload = this.propertiesLoad;
for i1 = 1:numel(objFNload)
this.(objFNload{i1}) = obj.(objFNsaved{i1});
end
end
end
end
......@@ -254,11 +268,13 @@ classdef itaHpTF_Audio < itaHpTF
end
function result = propertiesSaved
result = {'TF','fLower','fUpper','method','normalized','smoothing'};
result = {'nameHP','nameMic','nameSubj','repeat','mic','savePath',...
'TF','fLower','fUpper','method','normalized','smoothing'};
end
function result = propertiesLoad
result = {'mTF','m_fUpper','m_fLower','mMethod','mNormalized','mSmoothing'};
result = {'nameHP','nameMic','nameSubj','repeat','mic','savePath',...
'mTF','m_fUpper','m_fLower','mMethod','mNormalized','mSmoothing'};
end
function result = propertiesMethod
......
%% measure HpTF with GUI
HpTF_ms = itaHpTF_MS; % uses output and input channels 1,2
HpTF_subj = HpTF_ms.run %#ok<NOPTS> run measurement
HpTF_subj.TF.pf % show measured transfer functions
%% measure HpTF with a measurement setup
in = 1:2; % input channels
out = 1:2; % output channels
amp = -40; % output amplification
fftDeg = 16; % define fftDegree
MSTF = itaMSTF; % create measurement setup
MSTF.fftDegree = fftDeg;
MSTF.inputChannels = in;
MSTF.outputChannels = out;
MSTF.outputamplification = amp;
HpTF_ms = itaHpTF_MS(MSTF); % init HpTF measurement object
HpTF_ms.nameHP = 'HD 650'; % name of the headphones
HpTF_ms.nameMic = 'KE 3'; % name of the headphones
%HpTF_ms.mic % [transfer functions of the microphones]
HpTF_ms.nameSubj = name; % name of the subject
HpTF_ms.repeat = 4; % repeatitions [8]
HpTF_subj = HpTF_ms.run; % run measurement (press any button to continue
HpTF_subj.TF.pf % show measured transfer functions
%% calculate equalization curve (prepare HpTF)
HpTF_subj.method = 'mSTD'; % choose method [mSTD, mean, max]
HpTF_subj.smoothing = 1/6; % smoothing [1/6 octave bands]
HpTF_subj.fLower = 200; % [100 Hz] lowest frequency for the headphones (smooth spectrum below)
HpTF_subj.fUpper = 18000; % [18 kHz] highest freq for the headphones (regularization)
HpTF_eq = HpTF_subj.HP_equalization; % calculate equalization curve
HpTF_eq.pf
......@@ -9,9 +9,10 @@ tGuessSd = 3;
q = QuestCreate(tGuess,tGuessSd,pThreshold,beta,delta,gamma);
q.normalizePdf = 1;
trialsDesired=40;
trialsDesired=20;
wrongRight={'wrong','right'};
res = ones(trialsDesired,1);
for k=1:trialsDesired
% Get recommended level. Choose your favorite algorithm.
......@@ -20,10 +21,12 @@ for k=1:trialsDesired
% tTest=QuestMode(q); % Recommended by Watson & Pelli (1983)
% HERE IS MY CODE
response = round(rand(1,1));
%response = round(rand(1,1));
response = res(k);
q=QuestUpdate(q,tTest,response); % Add the new datum (actual test intensity and observer response) to the database.
disp(num2str(q.xThreshold))
disp(num2str(tTest))
end
% Ask Quest for the final estimate of threshold.
......
function [ out ] = ita_matlab2openGL( in )
%ITA_MATLAB2OPENGL converts either a itaCoordinates or a nx3 cartesian coordinates matrix from
%itaCoordinate system to the OpenGL system. Always returns a nx3 matrix.
% Detailed explanation goes here
MATRIX_MATLAB2OPENGL= [0 0 -1; -1 0 0; 0 1 0];
if isa(in,'itaCoordinates')
in=in.cart;
end
if ~(size(in,2)==3)
error('Input has to be itaCoordinates or nx3 matrix')
end
out=in*(MATRIX_MATLAB2OPENGL);
end
function [ out ] = ita_openGL2Matlab( in )
%ITA_OPENGL2MATLAB converts either a itaCoordinates or a nx3 cartesian coordinates matrix from
%OpenGL coordinate system to the itaCoordinate system. Always returns a nx3
%matrix.
% Detailed explanation goes here
MATRIX_MATLAB2OPENGL= [0 0 -1; -1 0 0; 0 1 0];
if isa(in,'itaCoordinates')
in=in.cart;
end
if ~(size(in,2)==3)
error('Input has to be itaCoordinates or nx3 matrix')
end
out=in*inv(MATRIX_MATLAB2OPENGL);
end
......@@ -6,26 +6,15 @@ function varargout = surf(this, varargin)
% </ITA-Toolbox>
titleString = [];
% sArgs = struct('pos1_data','double', 'parent', 0);
% [input,sArgs] = ita_parse_arguments(sArgs,varargin);
uniformPlot = 0;
numArgIn = nargin;
% this is the plot to a uniform sphere
if numArgIn == 3 && varargin{1} == 1
tmp = varargin{2};
clear varargin
varargin{1}= tmp;
clear tmp
uniformPlot = 1;
numArgIn = 2;
end
numArgIn = nargin;
if numArgIn == 2
% check if SH coefs are given
if numel(varargin{1}) > 0 &&...
% check if SH coefs are given
if numel(varargin{1}) > 0 &&...
this.nPoints ~= numel(varargin{1}) &&...
numel(this.Y) > 0 &&...
size(this.Y,1) == this.nPoints
......@@ -50,16 +39,12 @@ if numArgIn == 2
% change to complex drawing mode, if complex base is used
varargin{1}(1) = varargin{1}(1) + 1i * eps;
end
disp(['plotting SH-coefficients up to order ' num2str(this.nmax)]);
ita_verbose_info(['plotting SH-coefficients up to order ' num2str(this.nmax)],2);
nmaxVec = ceil(sqrt(nSHData)-1);
titleString = ['Spherical Harmonics coefficients, nmax = ' num2str(nmaxVec) '/' num2str(this.nmax) ' (data/grid)'];
end
end
if uniformPlot
varargin{2} = varargin{1};
varargin{1} = 1;
end
hFig = {surf@itaCoordinates(this, varargin{:})};
......
classdef itaRavenProject < itaHandle
classdef itaRavenProject < handle
%RavenProject - The class for working with RAVEN.
% This class allows you to create configurations of settings, to
% run simulations and to retrieve the results.
......@@ -30,7 +30,7 @@ classdef itaRavenProject < itaHandle
% Lukas Aspck (las@akustik.rwth-aachen.de)
% Version: 0.1
% First release: 01.11.10
% Last revision: 14.07.16
% Last revision: 12.09.16
% Copyright: Institute of Technical Acoustics, RWTH Aachen University
%
......@@ -192,7 +192,7 @@ classdef itaRavenProject < itaHandle
%---------------------- PUBLIC METHODS -------------------------------%
methods
%------------------------------------------------------------------
function obj = RavenProject(raven_project_file)
function obj = itaRavenProject(raven_project_file)
%RavenProject - constructor
% To Create a new project with empty default configuration.
%
......@@ -221,6 +221,10 @@ classdef itaRavenProject < itaHandle
end
end
function delete(obj)
obj.deleteResultsInRavenFolder();
end
%------------------------------------------------------------------
function setRavenExe(obj, newRavenExe)
obj.ravenExe = newRavenExe;
......@@ -380,6 +384,54 @@ classdef itaRavenProject < itaHandle
end
%------------------------------------------------------------------
function runNoGathering(obj)
% basicly the same as the run method, but without the call of
% obj.gatherResults();
obj.simulationDone = false;
if obj.projectLoaded
savedProjectName = obj.projectName;
obj.projectID = datestr(now, 30);
obj.projectTag = [obj.projectName obj.projectID];
% give the project name a date and time string to help to identify the results
obj.setProjectName(obj.projectTag);
% set filter length to the length of the reverberation
% obj.setFilterLengthToReverbTime();
% run the simulation
disp(['Running simulation... (' obj.ravenExe ')']);
if exist(obj.ravenLogFile, 'file')
delete(obj.ravenLogFile);
end
% system([obj.ravenExe ' "' obj.ravenProjectFile '" >> ' obj.ravenLogFile]);
dos([obj.ravenExe ' "' obj.ravenProjectFile '"'], '-echo');
disp('Done.');
% restore the initial project name
obj.setProjectName(savedProjectName);
% gather results
disp('This function does _not_ gather the results. Please provide arguments to getWallHitLogBand(band)');
% obj.gatherResults();
% disp('Done.');
obj.simulationDone = true;
% delete results in raven folder structure -> they are copied now into this class
% if (obj.keepOutputFiles == 0)
% obj.deleteResultsInRavenFolder();
% end
else
disp('No projected defined yet.');
end
end
%------------------------------------------------------------------
function numReceivers = createReceiverArray(obj, xpositions, zpositions, yheight)
numReceivers = numel(xpositions) * numel(zpositions);
......@@ -524,6 +576,33 @@ classdef itaRavenProject < itaHandle
obj.model.plotModel(tgtAxes, comp2axesMapping, wireframe);
end
end
% plot source and receivers
spos = obj.getSourcePosition;
snames = obj.getSourceNames;
rpos = obj.getReceiverPosition;
rnames = obj.getReceiverNames;
plot3(spos(:,3),spos(:,1),spos(:,2),'marker','o','markersize',9,'linestyle','none','linewidth',1.5)
plot3(rpos(:,3),rpos(:,1),rpos(:,2),'marker','x','markersize',9,'linestyle','none','linewidth',1.5)
% plot view/up vectors (red/green) of receivers
sview = obj.getSourceViewVectors;
sup = obj.getSourceUpVectors;
quiver3(spos(:,3),spos(:,1),spos(:,2),0.5*sview(:,3),0.5*sview(:,1),0.5*sview(:,2),'color','r','maxheadsize',1.5,'linewidth',1.5);
quiver3(spos(:,3),spos(:,1),spos(:,2),0.5*sup(:,3),0.5*sup(:,1),0.5*sup(:,2),'color','g','maxheadsize',1.5,'linewidth',1.5);
% plot view/up vectors (red/green) of receivers
rview = obj.getReceiverViewVectors;
rup = obj.getReceiverUpVectors;
quiver3(rpos(:,3),rpos(:,1),rpos(:,2),0.5*rview(:,3),0.5*rview(:,1),0.5*rview(:,2),'color','r','maxheadsize',1.5,'linewidth',1.5);
quiver3(rpos(:,3),rpos(:,1),rpos(:,2),0.5*rup(:,3),0.5*rup(:,1),0.5*rup(:,2),'color','g','maxheadsize',1.5,'linewidth',1.5);
% plot names
text(spos(:,3)+0.2,spos(:,1),spos(:,2),snames)
text(rpos(:,3)+0.2,rpos(:,1),rpos(:,2),rnames)
end
% [Global] %
......@@ -690,6 +769,11 @@ classdef itaRavenProject < itaHandle
obj.rpf_ini.WriteFile(obj.ravenProjectFile);
end
%------------------------------------------------------------------
function airAbsEnabled = getAirAbsorptionEnabled(obj)
airAbsEnabled = ~obj.rpf_ini.GetValues('Rooms', 'noAirAbsorption', 0);
end
% [PrimarySources] %
%------------------------------------------------------------------
function setSourceNames(obj, sourceNames)
......@@ -1056,7 +1140,7 @@ classdef itaRavenProject < itaHandle
end
%------------------------------------------------------------------
function setTimeSlotLength(obj, slotlength)
function setTimeSlotLength(obj, slotlength) % set timeslot lengt in ms !
obj.timeSlotLength = slotlength;
obj.rpf_ini.SetValues('RayTracing', 'timeResolution_DetectionSphere', slotlength);
obj.rpf_ini.SetValues('RayTracing', 'timeResolution_Portal', slotlength);
......@@ -1215,19 +1299,19 @@ classdef itaRavenProject < itaHandle
% print header
fprintf(fid, '[Material]\r\n');
fprintf(fid, ['name=' matname '\r\n']);
fprintf(fid, 'notes=Generated by MATLAB script (SPE)\r\n');
fprintf(fid, ['notes=Generated/Modified by MATLAB script (' datestr(now) ')\r\n']);
% parse input data
if length(alpha) == 1
alpha = ones(1,31) * alpha;
elseif length(alpha) ~= 31 && length(alpha) ~= 10
disp('ERROR! alpha has to be either of size=1 or size=31.');
disp('ERROR! alpha has to be a vector with the length 1,10, or 31.');