Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Institute of Technical Acoustics (ITA)
toolbox
Commits
151f6aaf
Commit
151f6aaf
authored
Oct 14, 2020
by
Hark Braren
Browse files
Moving sofa import of HRTFs to external function and clean up of HRTF class
parent
9e4cb72b
Changes
2
Hide whitespace changes
Inline
Side-by-side
applications/Binaural-HRTF/HRTF_class/@itaHRTF/itaHRTF.m
View file @
151f6aaf
...
...
@@ -110,10 +110,13 @@ classdef itaHRTF < itaAudio
itaAudio2itaHRTF
;
init
;
hdf2itaHRTF
;
sofa2itaHRTF
;
nDirections
=
[];
end
properties
(
Dependent
=
true
,
SetAccess
=
private
)
end
methods
% Special functions that implement operations that are usually performed only on instances of the class
%% Input
function
this
=
itaHRTF
(
varargin
)
...
...
@@ -155,7 +158,7 @@ classdef itaHRTF < itaAudio
end
% sofa input
if
~
isempty
(
find
(
strcmpi
(
varargin
,
'SOFA'
)
==
1
,
1
))
this
.
sofa2itaHRTF
=
v
arargin
{
find
(
strcmpi
(
varargin
,
'SOFA'
)
==
1
)
+
1
};
this
=
ita_read_sofa_hrtf
(
arargin
{
find
(
strcmpi
(
varargin
,
'SOFA'
)
==
1
)
+
1
}
)
;
end
elseif
nargin
==
1
...
...
@@ -188,9 +191,9 @@ classdef itaHRTF < itaAudio
this
.
itaAudio2itaHRTF
=
varargin
{
1
};
elseif
ischar
(
varargin
{
1
})
% openDaff/ sofa/ hdf5 input
if
strf
in
d
(
lower
(
varargin
{
1
}),
'.daff'
),
this
.
openDAFF2itaHRTF
=
varargin
{
1
};
elseif
strf
in
d
(
lower
(
varargin
{
1
}),
'.hdf5'
),
this
.
hdf2itaHRTF
=
varargin
{
1
};
elseif
strf
in
d
(
lower
(
varargin
{
1
}),
'.sofa'
),
this
.
sofa2itaHRTF
=
varargin
{
1
};
if
conta
in
s
(
lower
(
varargin
{
1
}),
'.daff'
),
this
.
openDAFF2itaHRTF
=
varargin
{
1
};
elseif
conta
in
s
(
lower
(
varargin
{
1
}),
'.hdf5'
),
this
.
hdf2itaHRTF
=
varargin
{
1
};
elseif
conta
in
s
(
lower
(
varargin
{
1
}),
'.sofa'
),
this
=
ita_read_sofa_hrtf
(
varargin
{
1
}
)
;
end
end
end
...
...
@@ -557,82 +560,7 @@ classdef itaHRTF < itaAudio
this
.
channelNames
=
ita_sprintf
(
'%s ( %2.0f, %2.0f)'
,
...
this
.
mEarSide
,
...
this
.
channelCoordinates
.
theta_deg
,
this
.
channelCoordinates
.
phi_deg
);
end
function
this
=
set
.
sofa2itaHRTF
(
this
,
pathFile
)
%% check if sofa is installed
if
~
exist
(
'SOFAstart.m'
,
'file'
)
error
(
'SOFA not installed. Run ita_sofa_install'
);
end
if
~
exist
(
pathFile
,
'file'
)
f
=
filesep
;
pathFile
=
[
SOFAdbPath
f
'SOFA'
f
pathFile
];
end
handleSofa
=
SOFAload
(
pathFile
);
% get the number of measurement positions
numPositions
=
length
(
handleSofa
.
SourcePosition
);
% data
% the data is saved as positions x channel x filterdata
this
.
samplingRate
=
handleSofa
.
Data
.
SamplingRate
;
data
=
zeros
(
size
(
handleSofa
.
Data
.
IR
,
3
),
numPositions
*
2
);
data
(:,
1
:
2
:
numPositions
*
2
)
=
squeeze
(
handleSofa
.
Data
.
IR
(:,
1
,:))
.'
;
data
(:,
2
:
2
:
numPositions
*
2
)
=
squeeze
(
handleSofa
.
Data
.
IR
(:,
2
,:))
.'
;
% coordinates
coordinates
=
ita_sofa_getCoordinates
(
handleSofa
,
'channelCoordinateType'
,
'SourcePosition'
);
% duplicate the coordinates for both channels
channelCoordinates
=
itaCoordinates
(
numPositions
*
2
);
channelCoordinates
.
x
(
1
:
2
:
numPositions
*
2
)
=
coordinates
.
x
;
channelCoordinates
.
x
(
2
:
2
:
numPositions
*
2
)
=
coordinates
.
x
;
channelCoordinates
.
y
(
1
:
2
:
numPositions
*
2
)
=
coordinates
.
y
;
channelCoordinates
.
y
(
2
:
2
:
numPositions
*
2
)
=
coordinates
.
y
;
channelCoordinates
.
z
(
1
:
2
:
numPositions
*
2
)
=
coordinates
.
z
;
channelCoordinates
.
z
(
2
:
2
:
numPositions
*
2
)
=
coordinates
.
z
;
% added view and up vector
this
.
objectViewVector
=
itaCoordinates
(
handleSofa
.
ListenerView
);
this
.
objectUpVector
=
itaCoordinates
(
handleSofa
.
ListenerUp
);
this
.
objectCoordinates
=
itaCoordinates
(
handleSofa
.
ListenerPosition
);
warning
(
'ITA_HRTF: Sofa Up and View vectors are ignored'
);
this
.
data
=
data
;
this
.
channelCoordinates
=
channelCoordinates
;
this
.
mDirCoord
=
coordinates
;
this
.
mEarSide
=
repmat
([
'L'
;
'R'
],
numPositions
,
1
);
this
.
signalType
=
'energy'
;
this
.
channelNames
=
ita_sprintf
(
'%s ( %2.0f, %2.0f)'
,
...
this
.
mEarSide
,
...
this
.
channelCoordinates
.
theta_deg
,
this
.
channelCoordinates
.
phi_deg
);
%% user data
userDataFields
=
{
'GLOBAL_Conventions'
,
'GLOBAL_Version'
,
'GLOBAL_SOFAConventions'
,
'GLOBAL_SOFAConventionsVersion'
...
,
'GLOBAL_APIName'
,
'GLOBAL_APIVersion'
,
'GLOBAL_ApplicationName'
,
'GLOBAL_ApplicationVersion'
,
'GLOBAL_AuthorContact'
...
,
'GLOBAL_Comment'
,
'GLOBAL_DataType'
,
'GLOBAL_History'
,
'GLOBAL_License'
,
'GLOBAL_Organization'
,
'GLOBAL_References'
...
,
'GLOBAL_RoomType'
,
'GLOBAL_Origin'
,
'GLOBAL_DateCreated'
,
'GLOBAL_DateModified'
,
'GLOBAL_Title'
,
'GLOBAL_DatabaseName'
...
,
'GLOBAL_RoomDescription'
,
'GLOBAL_ListenerShortName'
,
'API'
,
'ListenerPosition'
,
'ListenerPosition_Type'
,
'ListenerPosition_Units'
...
,
'EmitterPosition'
,
'EmitterPosition_Type'
,
'EmitterPosition_Units'
,
'RoomCornerA'
,
'RoomCornerA_Type'
,
'RoomCornerA_Units'
...
,
'RoomCornerB'
,
'RoomCornerB_Type'
,
'RoomCornerB_Units'
,
''
,
''
,
''
,
''
,
''
,
''
,
''
};
for
index
=
1
:
length
(
userDataFields
)
if
isfield
(
handleSofa
,
userDataFields
{
index
})
userData
.
(
userDataFields
{
index
})
=
handleSofa
.
(
userDataFields
{
index
});
end
end
this
.
userData
=
userData
;
end
end
%% .......................SET......................................
function
this
=
set
.
dirCoord
(
this
,
dirCoord
)
...
...
@@ -1700,7 +1628,7 @@ classdef itaHRTF < itaAudio
function
result
=
propertiesSphereType
result
=
{
'cap'
,
'ring'
,
'full'
,
'undefined'
};
end
end
end
applications/Binaural-HRTF/HRTF_class/ita_read_sofa_hrtf.m
0 → 100644
View file @
151f6aaf
function
result
=
ita
_
read
_
sofa
_
hrtf
(
filename
,
varargin
)
%
ITA
_
READ
_
SOFA
-
+++
Short
Description
here
+++
%
This
function
++++
FILL
IN
INFO
HERE
++*
%
<
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
:
Jan
Gerrit
Richter
--
Email
:
jan
.
richter
@
akustik
.
rwth
-
aachen
.
de
%
Created
:
30
-
Sep
-
2014
%
Updated
:
14
-
Oct
-
2020
Hark
Braren
--
Email
:
hark
.
braren
@
akustik
.
rwth
-
aachen
.
de
%%
Return
type
of
data
this
function
can
read
if
nargin
==
0
result
{
1
}
.
extension
=
'.
sofa
';
result
{
1
}
.
comment
=
'
SOFA
Files
(*.sofa)';
return
end
sArgs = struct('samplingRate',-1);
ita_parse_arguments(sArgs,varargin);
%% check if sofa is installed
if ~exist('SOFAstart.m','file')
error('SOFA not installed. Run ita_sofa_install');
end
%% Open the sofaFile
if ~exist(filename,'file')
f=filesep;
filename=[SOFAdbPath f 'SOFA' f filename];
end
handleSofa = SOFAload(filename);
%% check HRTF
isHrtf = ismember(handleSofa.GLOBAL_SOFAConventions,{'SimpleFreeFieldHRIR','SimpleFreeFieldHRTF','SimpleFreeFieldTF'});
if ~isHrtf
error("Datatype not typically used for HRTFs");
end
%% get positional data
% head position coordinates and orientation
recieverCoordinates = ita_sofa_getCoordinates(handleSofa,'coordinateType','ReceiverPosition');
listenerView = ita_sofa_getCoordinates(handleSofa,'coordinateType','ListenerView');
listenerUp = listenerView;
listenerUp.(listenerUp.coordSystem) = handleSofa.ListenerUp;
%source coordinates
sourceCoordinates = ita_sofa_getCoordinates(handleSofa,'coordinateType','SourcePosition');
%% get datatype info
switch handleSofa.GLOBAL_DataType
case 'TF'
audioData = getSofaFreqData(handleSofa);
case {'FIR','FIR-E','FIRE'}
audioData = getSofaTimeData(handleSofa);
case 'SOS'
error('SOS type not yet implemented for ITA-Toolbox');
end
% set direction
audioData(1).channelCoordinates = sourceCoordinates;
audioData(2).channelCoordinates = sourceCoordinates;
%% final data as HRTF
if isa(audioData,'itaResult')
result = audioData;
return
else
result = itaHRTF(audioData);
end
result.objectCoordinates = recieverCoordinates;
result.objectUpVector = listenerUp;
result.objectViewVector = listenerView;
%% add metaData as userData
result.userData = getSofaMetadata(handleSofa);
end
function audioData = getSofaTimeData(handleSofa)
data = handleSofa.Data.IR;
samplingrate = handleSofa.Data.SamplingRate;
if size(data,2) ~= 2
error('unknown data structure')
end
leftEarData = itaAudio(squeeze(data(:,1,:)).',samplingrate,'time');
rightEarData = itaAudio(squeeze(data(:,2,:)).',samplingrate,'time');
audioData = [leftEarData, rightEarData];
end
function [audioData] = getSofaFreqData(handleSofa,sArgs)
% handle frequency domain transfer functions:
% decide wether to return itaAudio or itaResult object
if ~ismember(handleSofa.N_LongName,{'f','frequency'})
error('Unspecified content of N in sofa object');
end
if ~ismember(handleSofa.N_Units,{'hertz','hz','Hertz','Hz'})
error('Uknown frequency unit in sofa object');
end
frequencies = handleSofa.N;
data = handleSofa.data.Real+1j*handleSofa.Data.Imag;
if std(diff(frequencies)) > 0.01*mean(diff(frequencies))
ita_verbose_info('Please check frequency Vector. It seems there are some values missing - returnin itaResult',0);
dataL = itaResult(squeeze(data(:,1,:)).',frequencies,'freq');
dataR = itaResult(squeeze(data(:,2,:)).',frequencies,'freq');
audioData = [dataL, dataR];
return
else
ita_verbose_info('Automatically converting from equidistantly sampled frequency domain data, handle with care',1)
end
if size(data,2) ~= 2
error('unknown data structure')
end
samplingrate = 2*max(fVec);
dataL = itaAudio(squeeze(data(:,1,:)).',samplingrate,'freq');
dataR = itaAudio(squeeze(data(:,2,:)).',samplingrate,'freq');
audioData = [dataL, dataR];
end
function result = getSofaMetadata(handleSofa)
% get meta data to keep with the ITA files
%list of possible dataFields
metaDataFields = {'GLOBAL_Conventions','GLOBAL_Version','GLOBAL_SOFAConventions','GLOBAL_SOFAConventionsVersion' ...
,'GLOBAL_APIName','GLOBAL_APIVersion','GLOBAL_ApplicationName','GLOBAL_ApplicationVersion','GLOBAL_AuthorContact' ...
,'GLOBAL_Comment','GLOBAL_DataType','GLOBAL_History','GLOBAL_License','GLOBAL_Organization','GLOBAL_References' ...
,'GLOBAL_RoomType','GLOBAL_Origin','GLOBAL_DateCreated','GLOBAL_DateModified','GLOBAL_Title','GLOBAL_DatabaseName' ...
,'GLOBAL_RoomDescription','GLOBAL_ListenerShortName','API','ListenerPosition','ListenerPosition_Type','ListenerPosition_Units'...
,'EmitterPosition','EmitterPosition_Type','EmitterPosition_Units','RoomCornerA','RoomCornerA_Type','RoomCornerA_Units' ...
,'RoomCornerB','RoomCornerB_Type','RoomCornerB_Units','','','','','','',''};
for index = 1:length(metaDataFields)
if isfield(handleSofa,metaDataFields{index})
result.(metaDataFields{index}) = handleSofa.(metaDataFields{index});
end
end
end %getSofaMetadata()
\ No newline at end of file
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment