From af047ddb1243368686440e802e444ee5d40cc145 Mon Sep 17 00:00:00 2001 From: Jan-Gerrit Richter Date: Wed, 19 Oct 2016 08:40:55 +0200 Subject: [PATCH] merged last svn commit into the git toolbox --- .../HRTF_class/@itaHRTF/itaHRTF.m | 306 ++++++++++-------- .../HRTF_class/@itaHRTF/writeDAFFFile.m | 21 +- .../Binaural-HRTF/HpTF_class/itaHpTF_Audio.m | 20 +- .../HpTF_class/ita_itaHpTF_examples.m | 36 +++ .../HRTFarc/ita_HRTFarc_postprocessing.m | 165 ++++++++++ .../test_rbo_questMean.m | 9 +- applications/SpatialAudio/ita_matlab2openGL.m | 18 ++ applications/SpatialAudio/ita_openGL2Matlab.m | 19 ++ .../VirtualAcoustics/Raven/itaRavenProject.m | 206 +++++++++++- .../VirtualAcoustics/Raven/ita_raven_demo.m | 2 +- .../openDAFF/AppDescription.txt | 0 .../openDAFF/OpenDAFFv1.5/DAFFv15.mexa64 | Bin .../openDAFF/OpenDAFFv1.5/DAFFv15.mexmaci64 | Bin .../openDAFF/OpenDAFFv1.5/DAFFv15.mexw32 | Bin .../openDAFF/OpenDAFFv1.5/DAFFv15.mexw64 | Bin .../OpenDAFFv1.5/DAFFv15_24june.mexmaci64 | Bin .../daffv15_convert_from_daffv17.m | 0 .../OpenDAFFv1.5/daffv15_create_dataset.m | 0 .../OpenDAFFv1.5/daffv15_effective_bounds.m | 0 .../daffv15_effective_filter_bounds.m | 0 .../openDAFF/OpenDAFFv1.5/daffv15_fpad16.m | 0 .../openDAFF/OpenDAFFv1.5/daffv15_lwrmul.m | 0 .../OpenDAFFv1.5/daffv15_metadata_addKey.m | 8 +- .../openDAFF/OpenDAFFv1.5/daffv15_uprmul.m | 0 .../openDAFF/OpenDAFFv1.5/daffv15_write.m | 0 .../OpenDAFFv1.5/daffv15_write_metadata.m | 10 +- .../openDAFF/OpenDAFFv1.5/itaDAFFv15.m | 0 .../OpenDAFFv1.5/itaDAFFv15_mergeThreeFiles.m | 0 .../OpenDAFFv1.5/itaDAFFv15_mergeTwoFiles.m | 0 .../openDAFF/OpenDAFFv1.5/private/Readme.txt | 0 .../openDAFF/OpenDAFFv1.5/private/dfBulbMS.m | 0 .../openDAFF/OpenDAFFv1.5/private/dfCubeMS.m | 0 .../OpenDAFFv1.5/private/dfDipoleMS.m | 0 .../openDAFF/OpenDAFFv1.5/private/dfDiscMS.m | 0 .../OpenDAFFv1.5/private/dfFrontalDiracMS.m | 0 .../private/dfFrontalHemisphereMS.m | 0 .../private/dfOmnidirectionalMS.m | 0 .../OpenDAFFv1.5/private/dfQuadrupoleMS.m | 0 .../openDAFF/OpenDAFFv1.5/private/dfStarMS.m | 0 .../OpenDAFFv1.5/private/dfUnitySphereMS.m | 0 .../private/dfUpperHemisphereMS.m | 0 .../private/exampleReadImpulseResponse.m | 0 .../private/exampleReadMagnitudeSpectrum.m | 0 .../private/exampleWriteMagnitudeSpectrum.m | 0 .../private/generateExampleDirectivities.m | 0 .../generateOmnidirectionalIRDatabase.m | 0 .../openDAFF/OpenDAFFv1.7/DAFFv17.mexw64 | Bin .../openDAFF/OpenDAFFv1.7/LICENSE.md | 0 .../openDAFF/OpenDAFFv1.7/README.md | 0 .../OpenDAFFv1.7/daffv17_add_metadata.m | 4 +- .../OpenDAFFv1.7/daffv17_convert_from_SH.m | 51 +++ .../daffv17_convert_from_daffv15.m | 24 +- .../OpenDAFFv1.7/daffv17_effective_bounds.m | 0 .../OpenDAFFv1.7/daffv17_generate_examples.m | 4 +- .../openDAFF/OpenDAFFv1.7/daffv17_lwrmul.m | 0 .../openDAFF/OpenDAFFv1.7/daffv17_uprmul.m | 0 .../openDAFF/OpenDAFFv1.7/daffv17_write.m | 20 +- .../OpenDAFFv1.7/daffv17_write_metadata.m | 0 .../datafuncs/dfConvertFromDAFFv15IR.m | 0 .../datafuncs/dfConvertFromDAFFv15MS.m | 5 + .../OpenDAFFv1.7/datafuncs/dfConvertFromSH.m | 23 ++ .../OpenDAFFv1.7/datafuncs/dfDiracIR.m | 0 .../datafuncs/dfFigureOfEightIR.m | 13 + .../datafuncs/dfFigureOfEightMS.m | 0 .../OpenDAFFv1.7/datafuncs/dfLowPass3dBMS.m | 2 +- .../OpenDAFFv1.7/datafuncs/dfLowPass6dBMS.m | 2 +- .../OpenDAFFv1.7/datafuncs/dfUnityDFT.m | 17 + .../OpenDAFFv1.7/datafuncs/dfUnityMS.m | 0 .../dfITAKunstkopfAcademic.m | 38 +++ .../export_ITAKunstkopfAcademic.m | 47 +++ .../daffv17_convert_from_miro.m | 81 +++++ .../hrtfs/TH_Koeln_AudioGroup/dfMIRO.m | 34 ++ .../example_convert_HRIR_FULL2DEG.m | 46 +++ ita_toolbox_setup.m | 2 +- kernel/DSP/Edit/ita_smooth.m | 4 +- kernel/StandardRoutines/ita_inputdlg.m | 66 ++++ kernel/StandardRoutines/ita_pause.m | 4 + kernel/StandardRoutines/ita_pause_ms.m | 4 + kernel/StandardRoutines/ita_pause_ns.m | 4 + kernel/StandardRoutines/ita_pause_us.m | 4 + 80 files changed, 1119 insertions(+), 200 deletions(-) create mode 100644 applications/Binaural-HRTF/HpTF_class/ita_itaHpTF_examples.m create mode 100644 applications/HRTFarc/ita_HRTFarc_postprocessing.m create mode 100644 applications/SpatialAudio/ita_matlab2openGL.m create mode 100644 applications/SpatialAudio/ita_openGL2Matlab.m rename applications/{ => VirtualAcoustics}/openDAFF/AppDescription.txt (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/DAFFv15.mexa64 (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/DAFFv15.mexmaci64 (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/DAFFv15.mexw32 (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/DAFFv15.mexw64 (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/DAFFv15_24june.mexmaci64 (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/daffv15_convert_from_daffv17.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/daffv15_create_dataset.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/daffv15_effective_bounds.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/daffv15_effective_filter_bounds.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/daffv15_fpad16.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/daffv15_lwrmul.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/daffv15_metadata_addKey.m (93%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/daffv15_uprmul.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/daffv15_write.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/daffv15_write_metadata.m (92%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/itaDAFFv15.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/itaDAFFv15_mergeThreeFiles.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/itaDAFFv15_mergeTwoFiles.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/Readme.txt (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/dfBulbMS.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/dfCubeMS.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/dfDipoleMS.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/dfDiscMS.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/dfFrontalDiracMS.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/dfFrontalHemisphereMS.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/dfOmnidirectionalMS.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/dfQuadrupoleMS.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/dfStarMS.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/dfUnitySphereMS.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/dfUpperHemisphereMS.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/exampleReadImpulseResponse.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/exampleReadMagnitudeSpectrum.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/exampleWriteMagnitudeSpectrum.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/generateExampleDirectivities.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.5/private/generateOmnidirectionalIRDatabase.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/DAFFv17.mexw64 (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/LICENSE.md (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/README.md (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/daffv17_add_metadata.m (96%) create mode 100644 applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_convert_from_SH.m rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/daffv17_convert_from_daffv15.m (83%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/daffv17_effective_bounds.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/daffv17_generate_examples.m (99%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/daffv17_lwrmul.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/daffv17_uprmul.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/daffv17_write.m (98%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/daffv17_write_metadata.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromDAFFv15IR.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromDAFFv15MS.m (75%) create mode 100644 applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromSH.m rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/datafuncs/dfDiracIR.m (100%) create mode 100644 applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfFigureOfEightIR.m rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/datafuncs/dfFigureOfEightMS.m (100%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass3dBMS.m (88%) rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass6dBMS.m (92%) create mode 100644 applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfUnityDFT.m rename applications/{ => VirtualAcoustics}/openDAFF/OpenDAFFv1.7/datafuncs/dfUnityMS.m (100%) create mode 100644 applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/ITAKunstkopfAcademic/dfITAKunstkopfAcademic.m create mode 100644 applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/ITAKunstkopfAcademic/export_ITAKunstkopfAcademic.m create mode 100644 applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/TH_Koeln_AudioGroup/daffv17_convert_from_miro.m create mode 100644 applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/TH_Koeln_AudioGroup/dfMIRO.m create mode 100644 applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/TH_Koeln_AudioGroup/example_convert_HRIR_FULL2DEG.m create mode 100644 kernel/StandardRoutines/ita_inputdlg.m create mode 100644 kernel/StandardRoutines/ita_pause.m create mode 100644 kernel/StandardRoutines/ita_pause_ms.m create mode 100644 kernel/StandardRoutines/ita_pause_ns.m create mode 100644 kernel/StandardRoutines/ita_pause_us.m diff --git a/applications/Binaural-HRTF/HRTF_class/@itaHRTF/itaHRTF.m b/applications/Binaural-HRTF/HRTF_class/@itaHRTF/itaHRTF.m index 1c93194a..3c4b0b4b 100644 --- a/applications/Binaural-HRTF/HRTF_class/@itaHRTF/itaHRTF.m +++ b/applications/Binaural-HRTF/HRTF_class/@itaHRTF/itaHRTF.m @@ -35,7 +35,7 @@ classdef itaHRTF < itaAudio % HRTF_left = getEar(earSide) % % itaHRTF Methods (play): -% play_gui(stimulus) +% play_gui(stimulus) % % itaHRTF Methods (store): % audioHRTF = itaHRTF2itaAudio @@ -45,16 +45,14 @@ classdef itaHRTF < itaAudio % ITD = ITD(varargin) % t0 = meanTimeDelay(varargin) % ILD = ILD(varargin) -% IACC = IACC(varargin) % % itaHRTF Methods (manipulation): % DTF = calcDTF % HRTF_int = interp(varargin) % % itaHRTF Methods (plot): -% plot_ILD -% plot_ITD(varargin) -% plot_freqSlice(varargin) +% plot_ITD(varargin) +% plot_freqSlice(varargin) % % See also: @@ -354,16 +352,16 @@ classdef itaHRTF < itaAudio end function this = set.openDaff2itaHRTF(this,pathDaff) - handleDaff = DAFFv17('open',pathDaff); - props = DAFFv17('getProperties', handleDaff); + handleDaff = DAFF('open',pathDaff); + props = DAFF('getProperties', handleDaff); counter = 1; data = zeros(props.filterLength,props.numRecords*2,'double' ) ; coordDaff = zeros(props.numRecords,2) ; for iDir = 1:props.numRecords - data(:,[counter counter+1]) = DAFFv17('getRecordByIndex', handleDaff,iDir)'; - %coordDaff(iDir,:) = DAFFv17('getRecordCoords', handleDaff, 'object', iDir)'; - coordDaff(iDir,:) = DAFFv17('getRecordCoords', handleDaff, 'data', iDir)'; + data(:,[counter counter+1]) = DAFF('getRecordByIndex', handleDaff,iDir)'; + %coordDaff(iDir,:) = DAFF('getRecordCoords', handleDaff, 'object', iDir)'; + coordDaff(iDir,:) = DAFF('getRecordCoords', handleDaff, 'data', iDir)'; counter= counter+2; end @@ -628,13 +626,17 @@ classdef itaHRTF < itaAudio phiU = rad2deg(this.phi_Unique); thetaU = rad2deg(this.theta_Unique); switch dirID - case 'phi_deg' + case {'phi_deg', 'p'} slice = this.findnearestHRTF(thetaU,dir_deg); - case 'theta_deg', + case {'theta_deg', 't'} slice = this.findnearestHRTF(dir_deg,phiU); end end + function slice = ss(this,dirID,dir_deg) + slice = this.sphericalSlice(dirID,dir_deg); + end + function HRTFout = getEar(this,earSide) switch earSide case 'L', @@ -895,9 +897,6 @@ classdef itaHRTF < itaAudio end end - %% Florian's Functions - - function cThis = interp(this,varargin) % function this = interp(varargin) % % Function to calculate HRTFs for arbitrary field points using a N-th order @@ -935,112 +934,8 @@ classdef itaHRTF < itaAudio % Author: Florian Pausch % Version: 2016-02-05 - % TODO: check why this is still not working (coordinate assignment???) - - sArgs = struct('order',50,'eps',1e-8); - sArgs = ita_parse_arguments(sArgs,varargin,2); - if ~isa(varargin{1},'itaCoordinates'),error('itaHRTF:interp', ' An itaCoordinate object is needed!') - end - field_in = varargin{1}; - - % only take unique direction coordinates (round to 1deg resolution) - tempfield = unique(round([field_in.phi_deg field_in.theta_deg]),'rows'); % may cause problems with older Matlab versions (<=R2013)! - temp_r = this.dirCoord.r(1); - field = itaCoordinates(size(tempfield,1)); - field.r = repmat(temp_r,size(tempfield,1),1); - field.phi_deg = tempfield(:,1); - field.theta_deg = tempfield(:,2); - - N = sArgs.order; - epsilon = sArgs.eps; % regularization parameter - k = this.wavenumber; % wave number - k(1) = eps; - % add eps to avoid NaN's - - Nmax = floor(sqrt(this.nDirections/4)-1); - - % construct vector of length (N+1)^2 regularization weights and, - % if needed, spherical hankel functions of second kind (for r0 and r1) - if ~isequal(this.dirCoord.r(1),field.r(1)) - kr0 = k*this.dirCoord.r(1); % measurement radius - kr1 = k*field.r(1); % extrapolation radius - - hankel_r0 = ita_sph_besselh(1:Nmax,2,kr0); - hankel_r1 = ita_sph_besselh(1:Nmax,2,kr1); - hankel_div = hankel_r1 ./ hankel_r0; - - hankel_rep = hankel_div(:,1); - end - - dweights = 1 + (0:Nmax).*((0:Nmax)+1); % calculate regularization weights - - dweights_rep = zeros(sum(2*(0:Nmax)'+1),1); - dweights_rep(1)=dweights(1); - counter = 2; - for n=1:Nmax - nTimes = 2*n+1; - dweights_rep(counter:counter+nTimes-1)=dweights(n+1)*ones(nTimes,1); - - if ~isequal(this.dirCoord.r(1),field.r(1)) - hankel_rep=[hankel_rep, repmat(hankel_div(:,n),1,2*n+1)]; - end - counter = counter + nTimes; - end - - %% Weights - [~,vWeights]= this.dirCoord.spherical_voronoi; % calculate weighting coefficients (Voronoi surfaces <-> measurement points) - W = diag(vWeights); % diagonal matrix containing weights - D = 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 - - %% Calculate HRTF data for field points - if Nmax > 25 - ita_disp('[itaHRTF.interp] Be patient...') - end - - % init. - hrtf_arbi = zeros(this.nBins,2*field.nPoints); % columns: LRLRLR... - for ear=1:2 - % calculate weighted SH coefficients using a decomposition order-dependent Tikhonov regularization - - freqData_temp = this.freqData(:,ear:2:end); - a0 = (Y.'*W*Y + epsilon*D) \ Y.'*W * freqData_temp.'; - %a0 = (Y.'*W*Y + epsilon*D) \ Y.' * - %this.freqData(:,ear:2:end).'; % fpa version - %a0 = pinv(Y)* this.freqData(:,ear:2:end).'; % jck version - - if ~isequal(this.dirCoord.r(1),field.r(1)) - % calculate range-extrapolated HRTFs - a1 = a0 .* hankel_rep.'; - - Yest = ita_sph_base(field,N,'orthonormal',false); % 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 - hrtf_arbi(:,ear:2:end) = (Yest*a0).'; % interpolated HRTFs - end - end - - % set new direction coordinates - sph = zeros(field.nPoints*2 ,3); - sph(1:2:end,:) = field.sph; - sph(2:2:end,:) = field.sph; - - % write new HRTF data set - cAudio = itaAudio(hrtf_arbi, 44100, 'freq'); - cAudio.channelCoordinates.sph= sph; - - cThis = itaHRTF(cAudio); - cThis.freqData = hrtf_arbi; + - if ~isequal(cThis.dirCoord.r(1),field.r(1))%??? - cThis.dirCoord.r = field.r; - end - - if N > 25 - ita_disp('[itaHRTF.interp] ...calculation finished!') - end - end function this = smooth_linphase(this,varargin) % function this = smooth_linphase(varargin) @@ -1221,10 +1116,10 @@ classdef itaHRTF < itaAudio end thetaC_deg = rad2deg(thisS.theta_Unique); - phiC_deg = rad2deg(thisS.phi_Unique); + phiC_deg = sort(mod(round(rad2deg(thisS.phi_Unique)),360)); nTheta = numel(thetaC_deg); nPhi = numel(phiC_deg); - coord = round(reshape(thisS.dirCoord.phi_deg,nTheta,nPhi)); + coord = reshape(mod(round(thisS.dirCoord.phi_deg),360),nTheta,nPhi); [~, idxC] = sort(coord,2); [~, idxCT] = unique(thisS.dirCoord.theta_deg); @@ -1245,7 +1140,7 @@ classdef itaHRTF < itaAudio set(gcf,'Position',[10 50 position(3:4)*0.85]); if strcmp(sArgs.method,'phase_delay') && ischar(sArgs.filter) % frequency dependent ITD pcolor(phiC_deg,this.freqVector,ITD) - title(strcat('\phi = ', num2str(round(thetaC_deg)), '°')) + title(strcat('\phi = ', num2str(round(thetaC_deg)), '�')) shading flat colorbar @@ -1286,7 +1181,7 @@ classdef itaHRTF < itaAudio xlabel('Azimuth Angle in Degree'); ylabel('ITD in Milliseconds'); set(gca,'xTick',0:30:360) - legend(ita_sprintf('%i°', round(thetaC_deg))) + legend(ita_sprintf('%i�', round(thetaC_deg))) end end @@ -1337,11 +1232,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 @@ -1382,6 +1277,165 @@ classdef itaHRTF < itaAudio grid on;set(gca,'layer','top') end + %% Jan's Functions + + + function writeDAFFFile(this, filePath) + % writes DAFF file to hard disc + % + % Input: filePath / fileName (string) + % + % Required: openDAFF matlab executables + % + % Output: none + + if nargin == 2 + fileName = filePath; + else + fileName = [ 'HRTF_Length' int2str(this.nSamples) '_' int2str(this.resAzimuth) 'x' int2str(this.resElevation) '.daff']; + end + + + %.............................................................. + % Comment: Angles are not exact - improve it if you like to :) + precision = 3; + nThetaU = numel(unique(round(this.channelCoordinates.theta_deg*10)./10)); + nPhiU = numel(unique(round(this.channelCoordinates.phi_deg*10)./10)); + + resElevation= round(median(diff(rad2deg(this.theta_Unique)))*10^precision)/10^precision; + rangeEl = round([min(rad2deg(this.theta_Unique)) max(rad2deg(this.theta_Unique))]*10^precision)/10^precision; + rangeElnew = [min(rangeEl) min(rangeEl)+(nThetaU-1)*resElevation]; + + resAzimuth= round(median(diff(rad2deg(this.phi_Unique)))*10^precision)/10^precision; + rangeAz = round([min(rad2deg(this.phi_Unique)) max(rad2deg(this.phi_Unique))]*10^precision)/10^precision; + rangeAznew = [min(rangeAz) min(rangeAz)+(nPhiU-1)*resAzimuth]; + %.............................................................. + + + %% config values + threshold_db = -20; + pre_taps = 12; + window_length = 128; + + delay = 10; + + gPeakL = 0; + gPeakR = 0; + gRangeStart = inf; + gRangeEnd = 0; + gRangeStartHit = []; + gRangeEndHit = []; + gPower = 0; + + + % Measurement distance [m], rounded on one digit + distance = delay / 44100 * 340; + distance = round(distance * 100)/100; + + % this = ita_time_shift(this,delay); + % metadata.object = 'ITA Kunstkopf, an artificial head developed and designed at the Institute of Technical Acoustics (ITA), RWTH Aachen University'; + % metadata.copyright = '(c) Copyright Institute of Technical Acoustics (ITA), RWTH Aachen University, Germany'; + % metadata.contact = 'Frank Wefers (fwe@akustik.rwth-aachen.de)'; + % metadata.environment = 'semi-anechoic chamber'; + % metadata.session = 'Mess01: Farfield HRIRs, Tobias Lentz, 2001'; + % metadata.processing = 'Loudspeaker deconvolved. Windowed using peak-oriented tukey window (0.1) to length 96 taps.'; + + %% find filter ranges + peak = max(abs(this.timeData)); + threshold = peak * 10^(threshold_db/20); + timeData = abs(this.timeData); + for index = 1:this.nChannels + kTemp = find(timeData(:,index) >=threshold(index)); + if (isempty(kTemp)) + error('Impulse response is completely below the threshold') + end + + r(index,:) = [ kTemp(1) kTemp(end) ]; + k{index} = kTemp; + end + + + + offset = max(r(:,1)-pre_taps,1); + + + for index = 1:this.nChannels + chObj = ita_time_window(this.ch(index),[offset(index) offset(index)+ window_length-1],'samples'); + timeData(:,index) = chObj.timeData; + + end + + copyObj = this; + copyObj.timeData = timeData; + copyCoordinates = copyObj.channelCoordinates; + copyCoordinates = copyCoordinates.build_search_database; + + + %% global peaks + + peak = max(abs(copyObj.timeData)); + threshold = peak * 10^(threshold_db/20); + timeData = abs(copyObj.timeData); + for index = 1:copyObj.nChannels + kTemp = find(timeData(:,index) >=threshold(index)); + if (isempty(kTemp)) + error('Impulse response is completely below the threshold') + end + + r(index,:) = [ kTemp(1) kTemp(end) ]; + k{index} = kTemp; + end + + + gRangeStart = min(r(r(:,1) > delay,1)); + gRangeEnd = max(r(r(:,2) < 1000,2)); + + + nDegree = log2(window_length); + + % create dataset + dataset = daff_create_dataset(... + 'alphares', resAzimuth, ... + 'alpharange',rangeAznew,... + 'betares', resElevation, ... + 'betarange', rangeElnew, ... + 'channels', 2); + + % set samplerate and metainfo + dataset.samplerate = this.samplingRate; + dataset.metadata.desc = 'Dummy HRTF'; + + dataset.metadata.delay_samples = int32(delay); + dataset.metadata.measurement_distance_meters = distance; + dataset.metadata.creation_date = datestr(now, 'yyyy-mm-dd HH:MM'); + % assign data + + + for i=1:dataset.numrecords + %dataset.records{i}.data = this.data(:,(2*i-1:2*i))'; + + alpha = dataset.records{i}.alpha; + beta = dataset.records{i}.beta; + + % get and save data + data = this.findnearestHRTF(180-beta,alpha); + % if ceil(nDegree) ~= floor(nDegree),data.nSamples = ceil(nDegree); + % end + + dataset.records{i}.data = data.timeData(gRangeStart:gRangeStart+window_length-1,:).'; + + + % Optionally you can supply individual metadata for the records + dataset.records{i}.metadata.filename = fileName; + end + + % write file + daff_write( 'filename', fileName, ... + 'content', 'IR', ... + 'dataset', dataset, 'verbose'); + + end + end methods(Hidden = true) function sObj = saveobj(this) diff --git a/applications/Binaural-HRTF/HRTF_class/@itaHRTF/writeDAFFFile.m b/applications/Binaural-HRTF/HRTF_class/@itaHRTF/writeDAFFFile.m index 737dfcf9..305a0047 100644 --- a/applications/Binaural-HRTF/HRTF_class/@itaHRTF/writeDAFFFile.m +++ b/applications/Binaural-HRTF/HRTF_class/@itaHRTF/writeDAFFFile.m @@ -1,7 +1,7 @@ -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 ); diff --git a/applications/Binaural-HRTF/HpTF_class/itaHpTF_Audio.m b/applications/Binaural-HRTF/HpTF_class/itaHpTF_Audio.m index a15d8a90..17056ee7 100644 --- a/applications/Binaural-HRTF/HpTF_class/itaHpTF_Audio.m +++ b/applications/Binaural-HRTF/HpTF_class/itaHpTF_Audio.m @@ -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 diff --git a/applications/Binaural-HRTF/HpTF_class/ita_itaHpTF_examples.m b/applications/Binaural-HRTF/HpTF_class/ita_itaHpTF_examples.m new file mode 100644 index 00000000..278e582c --- /dev/null +++ b/applications/Binaural-HRTF/HpTF_class/ita_itaHpTF_examples.m @@ -0,0 +1,36 @@ +%% measure HpTF with GUI +HpTF_ms = itaHpTF_MS; % uses output and input channels 1,2 +HpTF_subj = HpTF_ms.run %#ok 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 diff --git a/applications/HRTFarc/ita_HRTFarc_postprocessing.m b/applications/HRTFarc/ita_HRTFarc_postprocessing.m new file mode 100644 index 00000000..60578f4a --- /dev/null +++ b/applications/HRTFarc/ita_HRTFarc_postprocessing.m @@ -0,0 +1,165 @@ +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 diff --git a/applications/ListeningTests/DFG_Ex1_WallVariation/test_rbo_questMean.m b/applications/ListeningTests/DFG_Ex1_WallVariation/test_rbo_questMean.m index 61433e56..0c2b6627 100644 --- a/applications/ListeningTests/DFG_Ex1_WallVariation/test_rbo_questMean.m +++ b/applications/ListeningTests/DFG_Ex1_WallVariation/test_rbo_questMean.m @@ -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. diff --git a/applications/SpatialAudio/ita_matlab2openGL.m b/applications/SpatialAudio/ita_matlab2openGL.m new file mode 100644 index 00000000..babd76c4 --- /dev/null +++ b/applications/SpatialAudio/ita_matlab2openGL.m @@ -0,0 +1,18 @@ +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 + diff --git a/applications/SpatialAudio/ita_openGL2Matlab.m b/applications/SpatialAudio/ita_openGL2Matlab.m new file mode 100644 index 00000000..a06914f0 --- /dev/null +++ b/applications/SpatialAudio/ita_openGL2Matlab.m @@ -0,0 +1,19 @@ +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 + diff --git a/applications/VirtualAcoustics/Raven/itaRavenProject.m b/applications/VirtualAcoustics/Raven/itaRavenProject.m index 480e32c7..59841b3b 100644 --- a/applications/VirtualAcoustics/Raven/itaRavenProject.m +++ b/applications/VirtualAcoustics/Raven/itaRavenProject.m @@ -1,4 +1,4 @@ -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 Aspöck (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.'); return; end if length(scatter) == 1 scatter = ones(1,31) * scatter; elseif length(scatter) ~= 31 && length(scatter) ~= 10 - disp('ERROR! scatter has to be either of size=1 or size=31.'); + disp('ERROR! scatter has to be a vector with the length 1,10, or 31.'); return; end @@ -3118,15 +3202,23 @@ classdef itaRavenProject < itaHandle newMaterialNames = materialNames; end - % calculate new absorption values for the variable model to match the reverberation time of the target model (default values by eyring) - [A, S] = roommodel.getEquivalentAbsorptionArea(); - if numel(targetReverbTime) == 10 - A = A(3:3:end); % go to octave resolution + % calculate new absorption values for the variable model to match the reverberation time of the target model (default values by eyring including air abs) + [A, S] = roommodel.getEquivalentAbsorptionArea_eyring(); + if (obj.getAirAbsorptionEnabled) + airAbscoeffs = determineAirAbsorptionParameter(obj.getTemperature, obj.getPressure, obj.getHumidity); + else + airAbscoeffs = zeros(1,31); end - alphas_default = 1 - exp(-0.163 * roommodel.getVolume() ./ (S .* targetReverbTime)); - alphas_alt = A/S; - alphas_neu = 1 - (1 - alphas_alt(:)).^(thisReverbTime(:) ./ targetReverbTime(:)); + equivalentAirAbsorptionArea = 4* roommodel.getVolume() * airAbscoeffs; + if numel(targetReverbTime) == 10 % go to octave resolution + A = A(3:3:end); + equivalentAirAbsorptionArea = equivalentAirAbsorptionArea(3:3:end); + end + alphas_default = 1 - exp(((-0.163 * roommodel.getVolume() ./ targetReverbTime) - equivalentAirAbsorptionArea)/(S)); + alphas_alt = (A+equivalentAirAbsorptionArea)/S; + alphas_neu = 1 - (1 - alphas_alt(:)).^(thisReverbTime(:) ./ targetReverbTime(:)); + absorptionFactors = alphas_neu(:) ./ alphas_alt(:); absorptionFactors(isnan(absorptionFactors)) = 1; absorptionFactors(isinf(absorptionFactors)) = 999; @@ -3169,6 +3261,15 @@ classdef itaRavenProject < itaHandle nRT = numel(targetReverbTime); plot(1:nRT, targetReverbTime, 1:nRT, thisReverbTime, 1:nRT, newReverbTime); legend('Target RT', 'RT before', 'RT after'); + + ylabel('T30 [s]'); + xlabel('Frequency band [Hz]'); + ylim([0 1.1*max(targetReverbTime)]); + + ax = gca; + ax.XTickLabel = {32 63 125 250 500 1000 2000 4000 8000 16000}; + grid on; + else newReverbTime = []; end @@ -3596,7 +3697,8 @@ classdef itaRavenProject < itaHandle continue; end -% [wavedata{sourceID+1, receiverID+1}, obj.sampleRate,~] = wavread(filename{i}); + % LAS: wavread is not supported by Matlab versions newer than 2015a + % [wavedata{sourceID+1, receiverID+1}, obj.sampleRate,~] = wavread(filename{i}); [wavedata{sourceID+1, receiverID+1}, obj.sampleRate] = audioread(filename{i}); @@ -4299,6 +4401,47 @@ classdef itaRavenProject < itaHandle end end + + %------------------------------------------------------------------ + function getWallHitLogBand(obj,iBand) + + if obj.logPerformance + obj.initPerformanceData; + end + + disp('gatherResultsBand is called.'); + + if ~isnumeric(iBand) + error('Your argument has to be numeric and positive scalar.'); + end + + if obj.exportWallHitLog + wall_files_IS = obj.scan_output_folder(fullfile(obj.pathResults, obj.projectTag), {'WallHitLog_', ['_IS.log']}, '.log'); + wall_files_RT = obj.scan_output_folder(fullfile(obj.pathResults, obj.projectTag), {'WallHitLog_', ['[' num2str(iBand-1) ']_RT.log']}, '.log'); + + % read the wall hit logs back from disk + obj.wallHitLog_IS = obj.readWallHitLog_IS(wall_files_IS); + [obj.wallHitLog_RT, obj.initialParticleEnergy] = obj.readWallHitLog_RT(wall_files_RT); + else + obj.wallHitLog_IS = []; + obj.wallHitLog_RT = []; + obj.initialParticleEnergy = []; + end + + if obj.exportPlaneWaveList + planewave_files_IS = obj.scan_output_folder(fullfile(obj.pathResults, obj.projectTag), {'PlaneWaves_', ['_IS.txt']}, '.txt'); + planewave_files_RT = obj.scan_output_folder(fullfile(obj.pathResults, obj.projectTag), {'PlaneWaves_', ['[' num2str(iBand-1) ']_RT.txt']}, '.txt'); + + % read the plane wave lists back from disk + obj.planeWaveList_IS = obj.readPlaneWaveList(planewave_files_IS); + obj.planeWaveList_RT = obj.readPlaneWaveList(planewave_files_RT); + else + obj.planeWaveList_IS = []; + obj.planeWaveList_RT = []; + end + + disp(['Successfully gathered results from band ' num2str(iBand)]); + end end % public methods %---------------------- PRIVATE METHODS ------------------------------% @@ -4721,7 +4864,38 @@ classdef itaRavenProject < itaHandle disp('Error in RavenProject.powerSpectrum2energySpectrum: Unknown frequency resolution.'); energySpectrum = []; end - end + end + + %------------------------------------------------------------------ + function thisReverbTime = getT30_fromBinauralImpulseResponse(brir) + if ~iscell(brir) + brir = {brir}; + end + + thisReverbTime = cell(numel(brir), 1); + + for i = 1 : numel(brir) + if ~isempty(brir{i}) + disp('third-octave filtering'); + brir{i} = ita_mpb_filter(brir{i}, '3-oct'); + + disp('schroeder decay curve and reverberation time'); + thisReverbTime{i} = ita_roomacoustics_reverberation_time(brir{i}, 'edc_type','normal'); + + disp('average left and right ear''s reverberation time'); + if numel(thisReverbTime{i}) > 1 + thisReverbTime{i} = mean(thisReverbTime{i}); + end + thisReverbTime{i} = mean([thisReverbTime{i}.freqData(1:2:60) thisReverbTime{i}.freqData(2:2:60)], 2); + else + thisReverbTime{i} = []; + end + end + + if numel(thisReverbTime) == 1 + thisReverbTime = thisReverbTime{1}; + end + end %------------------------------------------------------------------ function value_out = averageAfterDIN(values_in, afterDIN) diff --git a/applications/VirtualAcoustics/Raven/ita_raven_demo.m b/applications/VirtualAcoustics/Raven/ita_raven_demo.m index b5ab163b..7c37e3eb 100644 --- a/applications/VirtualAcoustics/Raven/ita_raven_demo.m +++ b/applications/VirtualAcoustics/Raven/ita_raven_demo.m @@ -8,7 +8,7 @@ %% Projektdatei einlesen % project laden -rpf = RavenProject('..\RavenInput\Classroom\trilateration.rpf'); +rpf = itaRavenProject('..\RavenInput\Classroom\trilateration.rpf'); %% Simulationsparameter einstellen diff --git a/applications/openDAFF/AppDescription.txt b/applications/VirtualAcoustics/openDAFF/AppDescription.txt similarity index 100% rename from applications/openDAFF/AppDescription.txt rename to applications/VirtualAcoustics/openDAFF/AppDescription.txt diff --git a/applications/openDAFF/OpenDAFFv1.5/DAFFv15.mexa64 b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/DAFFv15.mexa64 similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/DAFFv15.mexa64 rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/DAFFv15.mexa64 diff --git a/applications/openDAFF/OpenDAFFv1.5/DAFFv15.mexmaci64 b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/DAFFv15.mexmaci64 similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/DAFFv15.mexmaci64 rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/DAFFv15.mexmaci64 diff --git a/applications/openDAFF/OpenDAFFv1.5/DAFFv15.mexw32 b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/DAFFv15.mexw32 similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/DAFFv15.mexw32 rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/DAFFv15.mexw32 diff --git a/applications/openDAFF/OpenDAFFv1.5/DAFFv15.mexw64 b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/DAFFv15.mexw64 similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/DAFFv15.mexw64 rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/DAFFv15.mexw64 diff --git a/applications/openDAFF/OpenDAFFv1.5/DAFFv15_24june.mexmaci64 b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/DAFFv15_24june.mexmaci64 similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/DAFFv15_24june.mexmaci64 rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/DAFFv15_24june.mexmaci64 diff --git a/applications/openDAFF/OpenDAFFv1.5/daffv15_convert_from_daffv17.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_convert_from_daffv17.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/daffv15_convert_from_daffv17.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_convert_from_daffv17.m diff --git a/applications/openDAFF/OpenDAFFv1.5/daffv15_create_dataset.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_create_dataset.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/daffv15_create_dataset.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_create_dataset.m diff --git a/applications/openDAFF/OpenDAFFv1.5/daffv15_effective_bounds.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_effective_bounds.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/daffv15_effective_bounds.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_effective_bounds.m diff --git a/applications/openDAFF/OpenDAFFv1.5/daffv15_effective_filter_bounds.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_effective_filter_bounds.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/daffv15_effective_filter_bounds.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_effective_filter_bounds.m diff --git a/applications/openDAFF/OpenDAFFv1.5/daffv15_fpad16.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_fpad16.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/daffv15_fpad16.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_fpad16.m diff --git a/applications/openDAFF/OpenDAFFv1.5/daffv15_lwrmul.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_lwrmul.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/daffv15_lwrmul.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_lwrmul.m diff --git a/applications/openDAFF/OpenDAFFv1.5/daffv15_metadata_addKey.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_metadata_addKey.m similarity index 93% rename from applications/openDAFF/OpenDAFFv1.5/daffv15_metadata_addKey.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_metadata_addKey.m index b30f2197..f8c22ff4 100644 --- a/applications/openDAFF/OpenDAFFv1.5/daffv15_metadata_addKey.m +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_metadata_addKey.m @@ -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. % - 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; diff --git a/applications/openDAFF/OpenDAFFv1.5/daffv15_uprmul.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_uprmul.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/daffv15_uprmul.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_uprmul.m diff --git a/applications/openDAFF/OpenDAFFv1.5/daffv15_write.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_write.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/daffv15_write.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_write.m diff --git a/applications/openDAFF/OpenDAFFv1.5/daffv15_write_metadata.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_write_metadata.m similarity index 92% rename from applications/openDAFF/OpenDAFFv1.5/daffv15_write_metadata.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_write_metadata.m index 5c925b4e..8d035adf 100644 --- a/applications/openDAFF/OpenDAFFv1.5/daffv15_write_metadata.m +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/daffv15_write_metadata.m @@ -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; diff --git a/applications/openDAFF/OpenDAFFv1.5/itaDAFFv15.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/itaDAFFv15.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/itaDAFFv15.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/itaDAFFv15.m diff --git a/applications/openDAFF/OpenDAFFv1.5/itaDAFFv15_mergeThreeFiles.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/itaDAFFv15_mergeThreeFiles.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/itaDAFFv15_mergeThreeFiles.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/itaDAFFv15_mergeThreeFiles.m diff --git a/applications/openDAFF/OpenDAFFv1.5/itaDAFFv15_mergeTwoFiles.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/itaDAFFv15_mergeTwoFiles.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/itaDAFFv15_mergeTwoFiles.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/itaDAFFv15_mergeTwoFiles.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/Readme.txt b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/Readme.txt similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/Readme.txt rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/Readme.txt diff --git a/applications/openDAFF/OpenDAFFv1.5/private/dfBulbMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfBulbMS.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/dfBulbMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfBulbMS.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/dfCubeMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfCubeMS.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/dfCubeMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfCubeMS.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/dfDipoleMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfDipoleMS.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/dfDipoleMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfDipoleMS.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/dfDiscMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfDiscMS.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/dfDiscMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfDiscMS.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/dfFrontalDiracMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfFrontalDiracMS.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/dfFrontalDiracMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfFrontalDiracMS.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/dfFrontalHemisphereMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfFrontalHemisphereMS.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/dfFrontalHemisphereMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfFrontalHemisphereMS.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/dfOmnidirectionalMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfOmnidirectionalMS.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/dfOmnidirectionalMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfOmnidirectionalMS.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/dfQuadrupoleMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfQuadrupoleMS.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/dfQuadrupoleMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfQuadrupoleMS.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/dfStarMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfStarMS.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/dfStarMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfStarMS.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/dfUnitySphereMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfUnitySphereMS.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/dfUnitySphereMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfUnitySphereMS.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/dfUpperHemisphereMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfUpperHemisphereMS.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/dfUpperHemisphereMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/dfUpperHemisphereMS.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/exampleReadImpulseResponse.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/exampleReadImpulseResponse.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/exampleReadImpulseResponse.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/exampleReadImpulseResponse.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/exampleReadMagnitudeSpectrum.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/exampleReadMagnitudeSpectrum.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/exampleReadMagnitudeSpectrum.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/exampleReadMagnitudeSpectrum.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/exampleWriteMagnitudeSpectrum.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/exampleWriteMagnitudeSpectrum.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/exampleWriteMagnitudeSpectrum.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/exampleWriteMagnitudeSpectrum.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/generateExampleDirectivities.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/generateExampleDirectivities.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/generateExampleDirectivities.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/generateExampleDirectivities.m diff --git a/applications/openDAFF/OpenDAFFv1.5/private/generateOmnidirectionalIRDatabase.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/generateOmnidirectionalIRDatabase.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.5/private/generateOmnidirectionalIRDatabase.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.5/private/generateOmnidirectionalIRDatabase.m diff --git a/applications/openDAFF/OpenDAFFv1.7/DAFFv17.mexw64 b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/DAFFv17.mexw64 similarity index 100% rename from applications/openDAFF/OpenDAFFv1.7/DAFFv17.mexw64 rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/DAFFv17.mexw64 diff --git a/applications/openDAFF/OpenDAFFv1.7/LICENSE.md b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/LICENSE.md similarity index 100% rename from applications/openDAFF/OpenDAFFv1.7/LICENSE.md rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/LICENSE.md diff --git a/applications/openDAFF/OpenDAFFv1.7/README.md b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/README.md similarity index 100% rename from applications/openDAFF/OpenDAFFv1.7/README.md rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/README.md diff --git a/applications/openDAFF/OpenDAFFv1.7/daffv17_add_metadata.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_add_metadata.m similarity index 96% rename from applications/openDAFF/OpenDAFFv1.7/daffv17_add_metadata.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_add_metadata.m index 21f6e89d..1245cee1 100644 --- a/applications/openDAFF/OpenDAFFv1.7/daffv17_add_metadata.m +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_add_metadata.m @@ -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 diff --git a/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_convert_from_SH.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_convert_from_SH.m new file mode 100644 index 00000000..9ff7ee6e --- /dev/null +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_convert_from_SH.m @@ -0,0 +1,51 @@ +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 diff --git a/applications/openDAFF/OpenDAFFv1.7/daffv17_convert_from_daffv15.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_convert_from_daffv15.m similarity index 83% rename from applications/openDAFF/OpenDAFFv1.7/daffv17_convert_from_daffv15.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_convert_from_daffv15.m index 923793ac..9fe44994 100644 --- a/applications/openDAFF/OpenDAFFv1.7/daffv17_convert_from_daffv15.m +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_convert_from_daffv15.m @@ -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, ... diff --git a/applications/openDAFF/OpenDAFFv1.7/daffv17_effective_bounds.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_effective_bounds.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.7/daffv17_effective_bounds.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_effective_bounds.m diff --git a/applications/openDAFF/OpenDAFFv1.7/daffv17_generate_examples.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_generate_examples.m similarity index 99% rename from applications/openDAFF/OpenDAFFv1.7/daffv17_generate_examples.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_generate_examples.m index 90d1a9ca..bc61f8c6 100644 --- a/applications/openDAFF/OpenDAFFv1.7/daffv17_generate_examples.m +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_generate_examples.m @@ -1,6 +1,6 @@ % 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) diff --git a/applications/openDAFF/OpenDAFFv1.7/daffv17_lwrmul.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_lwrmul.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.7/daffv17_lwrmul.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_lwrmul.m diff --git a/applications/openDAFF/OpenDAFFv1.7/daffv17_uprmul.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_uprmul.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.7/daffv17_uprmul.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_uprmul.m diff --git a/applications/openDAFF/OpenDAFFv1.7/daffv17_write.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_write.m similarity index 98% rename from applications/openDAFF/OpenDAFFv1.7/daffv17_write.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_write.m index 36651222..9f0c4431 100644 --- a/applications/openDAFF/OpenDAFFv1.7/daffv17_write.m +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_write.m @@ -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 diff --git a/applications/openDAFF/OpenDAFFv1.7/daffv17_write_metadata.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_write_metadata.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.7/daffv17_write_metadata.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/daffv17_write_metadata.m diff --git a/applications/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromDAFFv15IR.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromDAFFv15IR.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromDAFFv15IR.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromDAFFv15IR.m diff --git a/applications/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromDAFFv15MS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromDAFFv15MS.m similarity index 75% rename from applications/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromDAFFv15MS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromDAFFv15MS.m index 45db4214..293ee69f 100644 --- a/applications/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromDAFFv15MS.m +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromDAFFv15MS.m @@ -1,7 +1,12 @@ 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; [ metadata, empty ] = DAFFv15( 'getRecordMetadata', h, record_index ); diff --git a/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromSH.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromSH.m new file mode 100644 index 00000000..4358b73e --- /dev/null +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfConvertFromSH.m @@ -0,0 +1,23 @@ +function [ freqs, mags, metadata ] = dfConvertFromSH( alpha, beta, h ) + + freqs = h.radiation.bands.center_frequencies; + + direction = itaCoordinates( 1 ); + direction.r = 1.0; + direction.phi_deg = alpha; + direction.theta_deg = 180 - beta; + + h.sampling.cart = direction.cart; + h.sampling.nmax = h.radiation.N; % Updates SH base function + + %reference_value = abs( max( max( h.radiation.pnm( :, : ) ) ) ); + + numfreqs = length( freqs ); + mags = zeros( 1, numfreqs ); + for f = 1:numfreqs + mags( f ) = abs( h.sampling.Y * h.radiation.pnm( :, f ) ); %/ reference_value; + end + + metadata = []; + +end diff --git a/applications/openDAFF/OpenDAFFv1.7/datafuncs/dfDiracIR.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfDiracIR.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.7/datafuncs/dfDiracIR.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfDiracIR.m diff --git a/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfFigureOfEightIR.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfFigureOfEightIR.m new file mode 100644 index 00000000..a1210a6b --- /dev/null +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfFigureOfEightIR.m @@ -0,0 +1,13 @@ +function [ data, samplerate, metadata ] = dfFigureOfEightIR( alpha, beta, ~ ) + + channels = 1; + filter_length = 4; + samplerate = 48000.0; + + metadata = []; + + data = zeros( channels, filter_length ); + for c=1:size(data, 1) + data( c, 1 ) = cos( alpha * pi / 180.0 ) * sin( beta * pi / 180.0 ); % set first value only + end +end diff --git a/applications/openDAFF/OpenDAFFv1.7/datafuncs/dfFigureOfEightMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfFigureOfEightMS.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.7/datafuncs/dfFigureOfEightMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfFigureOfEightMS.m diff --git a/applications/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass3dBMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass3dBMS.m similarity index 88% rename from applications/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass3dBMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass3dBMS.m index faf258b5..5fbb75ef 100644 --- a/applications/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass3dBMS.m +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass3dBMS.m @@ -12,7 +12,7 @@ function [ freqs, mags, metadata ] = dfLowPass3dBMS( ~, ~, ~ ) for c=1:channels for f=1:length(freqs) - mags(c,f) = 1/f; + mags(c,f) = 1/2^(f-1); % Magnitude is a factor > 0 end end end diff --git a/applications/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass6dBMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass6dBMS.m similarity index 92% rename from applications/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass6dBMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass6dBMS.m index 262b0229..0565eb42 100644 --- a/applications/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass6dBMS.m +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfLowPass6dBMS.m @@ -12,7 +12,7 @@ function [ freqs, mags, metadata ] = dfLowPass6dBMS( ~, ~, ~ ) for c=1:channels for f=1:length(freqs) - mags(c,f) = 1/(2*f); + mags(c,f) = 1/(2^(2*(f-1))); end end end diff --git a/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfUnityDFT.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfUnityDFT.m new file mode 100644 index 00000000..289cb2e4 --- /dev/null +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfUnityDFT.m @@ -0,0 +1,17 @@ +function [ data, sampleRate, isSymetric, metadata ] = dfUnityDFT( ~, ~, ~ ) +% Omnidirectional discrete Fourier transform + + channels = 1; + bins = 128; + + data = zeros( channels, bins ); + metadata = []; + isSymetric = false; + sampleRate = 44100; + + for c = 1:channels + for n = 1:bins + data( c, n ) = 1.0 + 1i*0.0; + end + end +end diff --git a/applications/openDAFF/OpenDAFFv1.7/datafuncs/dfUnityMS.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfUnityMS.m similarity index 100% rename from applications/openDAFF/OpenDAFFv1.7/datafuncs/dfUnityMS.m rename to applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/datafuncs/dfUnityMS.m diff --git a/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/ITAKunstkopfAcademic/dfITAKunstkopfAcademic.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/ITAKunstkopfAcademic/dfITAKunstkopfAcademic.m new file mode 100644 index 00000000..d81d9c86 --- /dev/null +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/ITAKunstkopfAcademic/dfITAKunstkopfAcademic.m @@ -0,0 +1,38 @@ +function [ data, samplerate, metadata ] = dfITAKunstkopfAcademic( a, b, config ) + + file_base_name = sprintf( 'E%0.3dA%0.3d', b-90, a ); + + % Hack: unfortunately, there is no alpha 45° at elevation 135°. Map to front/back. + if b == 135 + mapped_a = a; + if mod( a, 90 ) ~= 0 + if a == 45 || a == 315 + mapped_a = 0; + elseif a == 135 || a == 225 + mapped_a = 180; + end + end + file_base_name = sprintf( 'E%0.3dA%0.3d', b-90, mapped_a ); + end + + file_path = fullfile( config.basepath, [ file_base_name '.WAV' ] ); + + if ~exist( file_path, 'file' ) + error( [ 'Could not find path "' file_path '", aborting.' ] ) + end + + [ y, Fs ] = audioread( file_path ); + samplerate = Fs; + data = y'; + + % We have to align to a multiple of 4 (OpenDAFF requires this for + % efficient data storage) + residual_samples = mod( size( data, 2 ), 4 ); + if residual_samples + data = [ data zeros( 2, 4 - residual_samples ) ]; + end + + metadata = []; + metadata = daff_add_metadata( metadata, 'FileBaseName', 'String', file_base_name ); + +end diff --git a/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/ITAKunstkopfAcademic/export_ITAKunstkopfAcademic.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/ITAKunstkopfAcademic/export_ITAKunstkopfAcademic.m new file mode 100644 index 00000000..a51ca8ef --- /dev/null +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/ITAKunstkopfAcademic/export_ITAKunstkopfAcademic.m @@ -0,0 +1,47 @@ +% +% OpenDAFF +% + +% The ITA Kunstkopf Academic HRIR data set can be obtained from: +% http://www.akustik.rwth-aachen.de/cms/Technische-Akustik/Studium/~edgv/Lehrmaterialien/ + +addpath( '../..' ) % Find daff_write and daff_add_metadata function + +metadata = []; +metadata = daff_add_metadata( metadata, 'Description', 'String', 'ITA Kunstkopf HRIR (Academic)' ); +metadata = daff_add_metadata( metadata, 'Creation date', 'String', date ); +metadata = daff_add_metadata( metadata, 'License', 'String', 'CC BY-NC 4.0' ); +metadata = daff_add_metadata( metadata, 'CC License Deed', 'String', 'https://creativecommons.org/licenses/by-nc/4.0/' ); +metadata = daff_add_metadata( metadata, 'Generation script', 'String', 'Opendaff-v1.7/matlab/hrtfs/ITAKunstkopfAcademic/export_ITAKunstkopfAcademic.m' ); +metadata = daff_add_metadata( metadata, 'Web Resource (2016)', 'String', 'http://www.akustik.rwth-aachen.de/cms/Technische-Akustik/Studium/~edgv/Lehrmaterialien/' ); + +config.basepath = 'ITA_Academic_HRIRs_2008-12-22/Standard'; +metadata_standard = daff_add_metadata( metadata, 'Postprocessing', 'String', 'Untouched' ); + +daff_write( 'filename', 'ITAKunstkopfAcademicStandard.ir.daff', ... + 'content', 'ir', ... + 'datafunc', @dfITAKunstkopfAcademic, ... + 'userdata', config, ... + 'channels', 2, ... + 'alphares', 45, ... + 'betares', 45, ... + 'betarange', [ 90 180 ], ... + 'orient', [ 0 0 0 ], ... + 'quantization', 'float32', ... + 'metadata', metadata_standard ); + + +config.basepath = 'ITA_Academic_HRIRs_2008-12-22/Free-field equalized'; +metadata_equalized = daff_add_metadata( metadata, 'Postprocessing', 'String', 'Free-field pressure equalized' ); + +daff_write( 'filename', 'ITAKunstkopfAcademicFreeFieldEqualized.ir.daff', ... + 'content', 'ir', ... + 'datafunc', @dfITAKunstkopfAcademic, ... + 'userdata', config, ... + 'channels', 2, ... + 'alphares', 45, ... + 'betares', 45, ... + 'betarange', [ 90 180 ], ... + 'orient', [ 0 0 0 ], ... + 'quantization', 'float32', ... + 'metadata', metadata_equalized ); diff --git a/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/TH_Koeln_AudioGroup/daffv17_convert_from_miro.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/TH_Koeln_AudioGroup/daffv17_convert_from_miro.m new file mode 100644 index 00000000..d0c0557c --- /dev/null +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/TH_Koeln_AudioGroup/daffv17_convert_from_miro.m @@ -0,0 +1,81 @@ +function [] = daffv17_convert_from_miro( miro_obj, target_file_path, additional_metadata ) +% +% daffv17_convert_from_miro Converts a MIRO object into DAFF +% +% miro_obj MIRO object containing IR data sets +% target_file_path [optional] target file path (uses name otherwise) +% +% This file is part of OpenDAFF, http://www.opendaff.org +% To obtain MIRO content, see http://audiogroup.web.th-koeln.de +% + +if nargin < 1 + error( 'No MIRO object given' ) +elseif nargin < 2 + target_file_path = [ miro_obj.name '.ir.v17.daff' ]; + additional_metadata = []; +elseif nargin < 3 + additional_metadata = []; +end + + +%% Auto-add props to metadata + +metadata = daffv17_add_metadata( additional_metadata, 'Converter Script', 'String', 'daffv17_convert_from_miro.m' ); + +metadata_field_names = fieldnames( miro_obj ); +for i = 1:size( metadata_field_names, 1 ) + key = metadata_field_names{i}; + switch( key ) + case { 'irChOne', 'irChTwo', 'headPhone', 'headPhoneComp', ... + 'shutUp', 'irCenter', 'azimuth', 'elevation', ... + 'quadWeight' } + continue; + end + + val = miro_obj.( key ); + if isempty( val ) || ( size( val, 1 ) > 1 ) || ( size( val, 2 ) > 1000 ) + continue + end + + if isnumeric( val ) + metadata = daffv17_add_metadata( metadata, key, 'Float', val ); + else + metadata = daffv17_add_metadata( metadata, key, 'String', val ); + end +end + + +%% Convert angles + +if ~strcmpi( miro_obj.quadGrid, 'Gauss-Leg. 16020SP (89E/180A)' ) + error( [ 'Incompatible grid ''' miro_obj.quadGrid '''' ] ); +end + +quadrature = miro_obj.getQuadrature; + +alphanums = size( unique( quadrature( :, 1 ) ), 1 ); +alpharange = rad2deg( [ min( miro_obj.azimuth ) max( miro_obj.azimuth ) ] ); +alphares = diff( alpharange ) / ( alphanums - 1 ); +if abs( alpharange( end ) + alphares ) - 360 < eps + alpharange( end ) = 360.0; +end + +betanums = size( unique( quadrature( :, 2 ) ), 1 ); +betarange = rad2deg( [ min( miro_obj.elevation ) max( miro_obj.elevation ) ] ); +betares = diff( betarange ) / ( betanums - 1 ); + +%$ Execute using data function 'dfMIRO' +daffv17_write( 'filename', target_file_path, ... + 'datafunc', @dfMIRO, ... + 'userdata', miro_obj, ... + 'metadata', metadata, ... + 'content', 'ir', ... + 'alphares', alphares, ... + 'alpharange', alpharange, ... + 'betares', betares, ... + 'betarange', betarange, ... + 'orient', [ 0 0 0 ], ... + 'channels', 2, ... + 'quantization', 'float32' ); + \ No newline at end of file diff --git a/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/TH_Koeln_AudioGroup/dfMIRO.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/TH_Koeln_AudioGroup/dfMIRO.m new file mode 100644 index 00000000..ecb9a71a --- /dev/null +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/TH_Koeln_AudioGroup/dfMIRO.m @@ -0,0 +1,34 @@ +function [ data, samplerate, metadata ] = dfMIRO( alpha, beta, miro_obj ) + + samplerate = miro_obj.fs; + if ~isempty( miro_obj.resampleToFS ) + samplerate = miro_obj.resampleToFS; + end + if strcmp( miro_obj.angles, 'DEG' ) + [ irID, azimuth, elevation ] = closestIr( miro_obj, alpha, beta ); + else + [ irID, azimuth, elevation ] = closestIr( miro_obj, deg2rad( alpha ), deg2rad( beta ) ); + end + hrir = getIR( miro_obj, irID ); + + nResidual = mod( size( hrir, 1 ), 4 ); + if nResidual > 0 + data = [ hrir' zeros( 2, 4 - nResidual ) ]; + else + data = hrir'; + end + + metadata = []; + if strcmp( miro_obj.angles, 'RAD' ) + azimuth = rad2deg( azimuth ); + elevation = rad2deg( elevation ); + end + + angle_threshold_deg = 0.2; + if abs( diff( [ azimuth alpha ] ) ) < angle_threshold_deg || ... + abs( diff( [ elevation beta ] ) < angle_threshold_deg ) + daffv17_add_metadata( metadata, 'MIRO Nearest Neighbour Search Applied', 'Bool', true ); + daffv17_add_metadata( metadata, 'MIRO Nearest Neighbour Azimuth', 'Float', azimuth ); + daffv17_add_metadata( metadata, 'MIRO Nearest Neighbour Elevation', 'Float', elevation ); + end +end diff --git a/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/TH_Koeln_AudioGroup/example_convert_HRIR_FULL2DEG.m b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/TH_Koeln_AudioGroup/example_convert_HRIR_FULL2DEG.m new file mode 100644 index 00000000..00f876ce --- /dev/null +++ b/applications/VirtualAcoustics/openDAFF/OpenDAFFv1.7/hrtfs/TH_Koeln_AudioGroup/example_convert_HRIR_FULL2DEG.m @@ -0,0 +1,46 @@ +% +% OpenDAFF +% +% Example how to convert the Neumann KU100 HRIR dataset from TH Köln +% AudioGroup into DAFF. +% + +%% Obtain from web resource + +% miro class +miro_url = 'http://audiogroup.web.th-koeln.de/FILES/miro.m'; +if exist( 'miro', 'class' ) == 0 + websave( 'miro.m', miro_url ); +end + +% Content +file_name = 'HRIR_FULL2DEG.mat'; +web_resource_url = [ 'http://audiogroup.web.th-koeln.de/FILES/' file_name ]; +if exist( file_name, 'file' ) == 0 + disp( [ 'Starting download from ' web_resource_url ] ) + file_path = websave( file_name, web_resource_url ); % Sometimes failing, better download manually +else + file_path = file_name; +end +load( file_path ) % makes HRIR_FULL2DEG available in workspace + + +%% Convert + +% ... very simple +daffv17_convert_from_miro( HRIR_FULL2DEG ); + +% ... with file name +daffv17_convert_from_miro( HRIR_FULL2DEG, 'HRIR_FULL2DEG.v17.ir.daff' ); + +% ... with extra metadata +additional_metadata = daffv17_add_metadata( [], 'Conversion date', 'String', date ); +additional_metadata = daffv17_add_metadata( additional_metadata, 'Web resource', 'String', web_resource_url ); +additional_metadata = daffv17_add_metadata( additional_metadata, 'License', 'String', 'CC BY-SA 3.0' ); +additional_metadata = daffv17_add_metadata( additional_metadata, 'License URL', 'String', 'http://creativecommons.org/licenses/by-sa/3.0/legalcode' ); +additional_metadata = daffv17_add_metadata( additional_metadata, 'CC license deed', 'String', 'https://creativecommons.org/licenses/by-sa/3.0/' ); +daffv17_convert_from_miro( HRIR_FULL2DEG, 'HRIR_FULL2DEG_48kHz_web.v17.ir.daff', additional_metadata ); + +% ... with resampling to common 44.1 kHz +HRIR_FULL2DEG.resampleToFS = 44.1e3; +daffv17_convert_from_miro( HRIR_FULL2DEG, 'HRIR_FULL2DEG_44kHz_web.v17.ir.daff', additional_metadata ); diff --git a/ita_toolbox_setup.m b/ita_toolbox_setup.m index 9ca9924b..4dff5487 100644 --- a/ita_toolbox_setup.m +++ b/ita_toolbox_setup.m @@ -5,7 +5,7 @@ function varargout = ita_toolbox_setup(varargin) % Call: ita_toolbox_setup % % See also ita_toolbox_documentation. -%fdjksajödkflj + % Reference page in Help browser % doc ita_toolbox_setup % diff --git a/kernel/DSP/Edit/ita_smooth.m b/kernel/DSP/Edit/ita_smooth.m index c67ba35e..c1881c0d 100644 --- a/kernel/DSP/Edit/ita_smooth.m +++ b/kernel/DSP/Edit/ita_smooth.m @@ -317,7 +317,7 @@ for ind = 1:numel(audioObject) case 'abs+phase' for k=1:channels SignalCentAbs = interp1(freq, abs(audioObj.freqData(:,k)), fCent); - SignalCentPhase = interp1(freq, angle(audioObj.freqData(:,k)), fCent); + SignalCentPhase = interp1(freq, unwrap(angle(audioObj.freqData(:,k))), fCent); signalCentSmoothAbs = feval(smooth_helper, SignalCentAbs , span, smooth_opt{:}); signalCentSmoothPhase = feval(smooth_helper, SignalCentPhase, span, smooth_opt{:}); absOut = interp1(fCent(2:end), signalCentSmoothAbs(2:end), freq(2:end), 'spline'); @@ -420,7 +420,7 @@ for ind = 1:numel(audioObject) case 'abs+phase' signalAbs = abs(audioObj.freqData); - signalPhase = angle(audioObj.freqData); + signalPhase = unwrap(angle(audioObj.freqData)); for k=1:nBins absOut(k,:) = 1./(upperBoundaryBins(k)-lowerBoundaryBins(k)+1) .* ... sum(signalAbs(lowerBoundaryBins(k):upperBoundaryBins(k),:), 1); diff --git a/kernel/StandardRoutines/ita_inputdlg.m b/kernel/StandardRoutines/ita_inputdlg.m new file mode 100644 index 00000000..db695574 --- /dev/null +++ b/kernel/StandardRoutines/ita_inputdlg.m @@ -0,0 +1,66 @@ +function output = ita_inputdlg(prompt,defaultanswer,defaultscreen) +% output = ita_inputdlg(prompt,defaultanswer) +% prompt ... figure title [string] +% defaultanswer ... default text of edit box [double] or [string] +% defaultscreen ... screen number to display dialog [double] +% +% Works similar to Matlab's inputdlg except that you can return with +% 'Enter' key and enter a screen number. +% +% Original code by Matt Fig, Matlab newsgroup (https://de.mathworks.com/matlabcentral/newsreader/view_thread/295157) +% Date: 30 Oct, 2010 00:18:03 (pretty early) +% +% Modified by: Florian Pausch, fpa@akustik.rwth-aachen.de +% Version: 2016-07-25 + +if nargin<1 + error('Input error! Please read function description.') +elseif nargin<2 + defaultanswer = NaN; + prompt = 'ita_inputdlg'; +elseif nargin<3 + defaultscreen = 1; +end + +if ~ischar(defaultanswer) + defaultanswer = num2str(defaultanswer); +end + +scrpos = get(0,'MonitorPositions'); +scrpos = scrpos(defaultscreen,:); + +output = []; % In case the user closes the GUI. +S.fh = figure('units','normalized',... + 'position',[scrpos(1)+scrpos(3)/2-0.1 0.4 0.105 0.09],... + 'menubar','none',... + 'numbertitle','off',... + 'name',prompt,... + 'resize','off'); +S.ed = uicontrol('style','edit',... + 'units','pix',... + 'position',[10 60 180 30],... + 'string',defaultanswer); +S.pb = uicontrol('style','pushbutton',... + 'units','pix',... + 'position',[10 20 180 30],... + 'string','OK',... + 'callback',{@pb_call}); +set(S.ed,'call',@ed_call) +uistack(S.fh,'top') +uicontrol(S.ed) % Make the editbox active. +uiwait(S.fh) % Prevent all other processes from starting until closed. + + function [] = pb_call(varargin) + output = str2double(get(S.ed,'string')); + close(S.fh); % Closes the GUI, allows the new output to be returned. + end + + function [] = ed_call(varargin) + uicontrol(S.pb) + drawnow + output = str2double(get(S.ed,'string')); + close(gcbf) + end + +end + diff --git a/kernel/StandardRoutines/ita_pause.m b/kernel/StandardRoutines/ita_pause.m new file mode 100644 index 00000000..a4dd003c --- /dev/null +++ b/kernel/StandardRoutines/ita_pause.m @@ -0,0 +1,4 @@ +function [] = ita_pause( seconds ) +% ita_pause pauses (sleeps) for given time (units in seconds) + java.util.concurrent.locks.LockSupport.park( seconds * 1e9 ) ); +end diff --git a/kernel/StandardRoutines/ita_pause_ms.m b/kernel/StandardRoutines/ita_pause_ms.m new file mode 100644 index 00000000..e876576d --- /dev/null +++ b/kernel/StandardRoutines/ita_pause_ms.m @@ -0,0 +1,4 @@ +function [] = ita_pause_ms( milli_seconds ) +% ita_pause_ms pauses (sleeps) for given time (units in milliseconds) + java.util.concurrent.locks.LockSupport.parkNanos( milli_seconds * 1e6 ); +end diff --git a/kernel/StandardRoutines/ita_pause_ns.m b/kernel/StandardRoutines/ita_pause_ns.m new file mode 100644 index 00000000..86f51663 --- /dev/null +++ b/kernel/StandardRoutines/ita_pause_ns.m @@ -0,0 +1,4 @@ +function [] = ita_pause_ns( nano_seconds ) +% ita_pause_ns pauses (sleeps) for given time (units in nanoseconds) + java.util.concurrent.locks.LockSupport.parkNanos( nano_seconds ); +end diff --git a/kernel/StandardRoutines/ita_pause_us.m b/kernel/StandardRoutines/ita_pause_us.m new file mode 100644 index 00000000..68e99b23 --- /dev/null +++ b/kernel/StandardRoutines/ita_pause_us.m @@ -0,0 +1,4 @@ +function [] = ita_pause_us( micro_seconds ) +% ita_pause_us pauses (sleeps) for given time (units in micro seconds) + java.util.concurrent.locks.LockSupport.parkNanos( micro_seconds * 1e3 ); +end -- GitLab