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

merged last svn commit into the git toolbox

parent be0de230
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 );
......
......@@ -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
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
......@@ -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
......@@ -8,7 +8,7 @@
%% Projektdatei einlesen
% project laden
rpf = RavenProject('..\RavenInput\Classroom\trilateration.rpf');
rpf = itaRavenProject('..\RavenInput\Classroom\trilateration.rpf');
%% Simulationsparameter einstellen
......
......@@ -9,11 +9,11 @@ function [ metadata ] = daffv15_metadata_addKey(metadata, keyname, datatype, val
% You can find the license for this m-file in the application folder.
% </ITA-Toolbox>
if (~isempty(metadata))
if (~isstruct(metadata)), error(['[' mfilename '] Wrong datatype for metadata']); end;
else
% if (~isempty(metadata))
% if (~isstruct(metadata)), error(['[' mfilename '] Wrong datatype for metadata']); end;
% else
metadata = struct('name', {}, 'datatype', {}, 'value', {});
end
% end
if (~ischar(keyname)), error(['[' mfilename '] Key name must be a string']); end;
......
......@@ -26,10 +26,10 @@ function [ ] = daffv15_write_metadata( fid, metadata )
% Check old metadata format and convert (for convenience)
if nkeys == 1
metadata_new_format = [];
fieldnames( metadata );
for i=1:length( fieldnames )
name = filednames( i );
value = metadata.(name);
metadata_fieldnames = fieldnames( metadata );
for i=1:length(metadata_fieldnames)
name = metadata_fieldnames{i};
eval([' value = metadata.' name ]);
type = '';
% Logical scalar (DAFF_BOOL)
......@@ -56,7 +56,7 @@ function [ ] = daffv15_write_metadata( fid, metadata )
error( 'Unsupported datatype %s for key ''%s'' in metadata', class( value ), name );
end
daffv15_metadata_addKey( metatada_new_format, name, type, value );
metadata_new_format = daffv15_metadata_addKey( metadata_new_format, name, type, value );
end
metadata = metadata_new_format;
......
......@@ -43,9 +43,9 @@ function [ metadata ] = daffv17_add_metadata(metadata, keyname, datatype, value)
case 'STRING'
if (~ischar(value)), error(['[' mfilename '] Value must be a string for string keys']); end;
metadata(end+1) = struct('name', keyname, 'datatype', 3, 'value', value);
metadata(end+1) = struct('name', keyname, 'datatype', 3, 'value', value);
otherwise
error( [ 'Unrecognized value type "' datatype '", use BOOL INT FLOAT or STRING' ] );
error( [ 'Unrecognized value type "' datatype '", use BOOL INT FLOAT or STRING' ] );
end
end
function daffv17_convert_from_SH( input_data_sh, export_file_path, additional_metadata )
% Reads a spherical harmonics data set and
% exports a DAFF file
%
% input_data_sh Input file path to DAFF v1.5 content
% export_file_path Output file path (will be DAFF v1.7 content)
% additional_metadata Extend metadata of target file (must be a daffv17 metadata)
%
default_leg_degree = 5; % default value for alphares, betares if not in input struct
if nargin < 3
additional_metadata = [];
end
metadata_v17 = daffv17_add_metadata( additional_metadata, 'Converter script', 'String', 'daffv17_convert_from_SH' );
metadata_v17 = daffv17_add_metadata( metadata_v17, 'Defita_svn_u', 'String', 'Converted from DAFF version 1.5' );
metadata_v17 = daffv17_add_metadata( metadata_v17, 'Date of conversion', 'String', date );
if ~isfield( input_data_sh, 'radiation' )
error( 'Invalid input: spherical harmonics data misses "radiation" key.' )
end
if ~isfield( input_data_sh, 'sampling' )
warning( 'Spherical harmonics data misses \"sampling\" key, using default gaussian grid with %ix%i degree legs.', default_leg_degree, default_leg_degree )
nmax_grid = 30;
input_data_sh.sampling = ita_sph_sampling_gaussian( nmax_grid );
input_data_sh.alphares = default_leg_degree;
input_data_sh.betares = default_leg_degree;
end
if ~isfield( input_data_sh, 'alphares' )
input_data_sh.alphares = default_leg_degree;
end
if ~isfield( input_data_sh, 'betares' )
input_data_sh.betares = default_leg_degree;
end
daffv17_write( 'filename', export_file_path, ...
'metadata', metadata_v17, ...
'datafunc', @dfConvertFromSH, ...
'userdata', input_data_sh, ...
'content', 'ms', ...
'channels', 1, ...
'alphares', input_data_sh.alphares, ...
'betares', input_data_sh.betares, ...
'orient', [ 0 0 0 ] );
end
......@@ -19,22 +19,24 @@ function [] = daffv17_convert_from_daffv15( daffv15_input_file_path, daffv17_out
metadata_v17 = daffv17_add_metadata( metadata_v17, 'Converter', 'String', 'Converted from DAFF version 1.5' );
metadata_v17 = daffv17_add_metadata( metadata_v17, 'Date of conversion', 'String', date );
metadata_v15 = DAFFv15( 'getMetadata', h );
metadata_v15 = DAFFv15( 'getMetadata', h );
metadata_field_names = fieldnames( metadata_v15 );
for i = size( metadata_field_names, 1 )
key = metadata_field_names{i};
val = metadata_v15.( key );
if isnumeric( val )
val = num2str( val );
metadata_field_names = fieldnames( metadata_v15 );
if size( metadata_field_names, 1 )
for i = size( metadata_field_names, 1 )
key = metadata_field_names{i};
val = metadata_v15.( key );
if isnumeric( val )
val = num2str( val );
end
metadata_v17 = daffv17_add_metadata( metadata_v17, key, 'String', val );
end
metadata_v17 = daffv17_add_metadata( metadata_v17, key, 'String', val );
end
end
switch( props.contentType )
case { 'ms', 'mps', 'ps' }
daffv17_write( 'filename', daffv17_output_file_path, ...
case { 'ms', 'mps', 'ps' }
daffv17_write( 'filename', daffv17_output_file_path, ...
'metadata', metadata_v17, ...
'datafunc', @dfConvertFromDAFFv15MS, ...
'userdata', h, ...
......
% 5x5 degree grid resolution
alpha_res = 5;
beta_res = 5;
alpha_res = 15;
beta_res = 15;
channels = 1;
default_orient = [0 0 0]; % yaw pitch roll @ +Y+X-Z (OpenGL)
......
......@@ -260,12 +260,12 @@ function [] = daffv17_write( varargin )
end
if isfield(args, 'alphares')
args.alphapoints = alphaspan / args.alphares;
if abs( args.alphapoints - args.alphapoints ) > eps
error( 'Alpha range and alpha resolution are not an integer multiple' )
args.alphapoints = round(alphaspan / args.alphares);
if (ceil(args.alphapoints) ~= args.alphapoints)
error('Alpha range and alpha resolution are not an integer multiple')
end
else
args.alphares = alphaspan / args.alphapoints;
args.alphares = round(alphaspan / args.alphapoints);
end
% Beta points and resolution
......@@ -285,11 +285,9 @@ function [] = daffv17_write( varargin )
end
if isfield(args, 'betares')
args.betapoints = (betaspan / args.betares) + 1;
if (abs(ceil(args.betapoints)- args.betapoints) > 1e-14)
args.betapoints = round((betaspan / args.betares) + 1);
if (ceil(args.betapoints) ~= args.betapoints)
error('Beta range and beta resolution are not an integer multiple')
else
args.betapoints = round(args.betapoints);
end
else
args.betares = betaspan / (args.betapoints-1);
......@@ -417,9 +415,7 @@ function [] = daffv17_write( varargin )
props.transformSize = 0;
% Generate a list of all individual input data sets
% note: use round here to avoid errors if alphapoints are not exactly
% integers but within epsilon
x = cell( round( args.alphapoints ), round( args.betapoints ), args.channels );
x = cell( args.alphapoints, args.betapoints, args.channels );
for b=1:args.betapoints
beta = betastart + (b-1)*args.betares;
......@@ -933,7 +929,7 @@ function [] = daffv17_write( varargin )
% Number of frequencies
fwrite(fid, props.numDFTCoeffs, 'int32');
fwrite(fid, props.transformSize, 'int32');
fwrite(fid, props.sampleRate, 'float32');
fwrite(fid, props.sampleRate, 'int32');
fwrite(fid, props.globalPeak, 'float32');
end
......
function [ freqs, mags, metadata ] = dfConvertFromDAFFv15MS( alpha, beta, h )
[ record_index, out_of_bounds ] = DAFFv15( 'getNearestNeighbourIndex', h, 'data', alpha, beta );
assert( not ( out_of_bounds == 1 ) );
% if you want to transform magnitudes into amplitudes
%mags = 10.^( DAFFv15( 'getRecordByIndex', h, record_index ) ./ 10 );
% else
mags = DAFFv15( 'getRecordByIndex', h, record_index );
props = DAFFv15( 'getProperties', h );
freqs = props.freqs